Logical expression evaluation [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last month.
Improve this question
I don't understand how to evaluate w1 and w1.
I know i>1 is 0, j<0 is 0, i<0 is 1, j>0 is 1 and so on, but how do I associate these values?
#include <stdio.h>
int main(void)
{
int i = -1, j = -i;
int w1, w2;
w1 = (i > 0) && (j < 0) || (i < 0) && (j > 0);
w2 = (i <= 0) || (j = 0) && (i >= 0) || (j <= 0);
printf("%d", w1 == w2);
return 0;
}
w1=1 and w2=0 but I know that is incorrect. Can someone explain in detail the process?

This is obfuscated code with a load of bad practice. The mainstream C compilers will tell you about some of the problems if compiling with max warnings enabled.
It's considered bad practice to mix a lot of && and || on a single line without parenthesis around their respective operands.
It is also bad practice to use assignment inside complex expressions.
Relevant operator precedence here is: () parenthesis highest, then &&, then || and = has the lowest precedence. So your expressions are equivalent to this:
w1 = ((i > 0) && (j < 0)) || ((i < 0) && (j > 0));
w2 = (i <= 0) || ((j = 0) && (i >= 0)) || (j <= 0);
From there on you can replace each inner parenthesis subexpression with boolean logic values.
Note the cheeky (j = 0)! This is not equivalence but assignment. Also gcc-like compilers will sadly not warn for this. The only reason why the code is still well-defined despite that assignment, is because the logical AND and OR operators are guaranteed to be sequenced left-to-right and in this case (expr1) || (expr2) guarantees that the expr1 containing the assignment is executed before expr2 where that assigned variable is used again.
With that crappy assignment in mind, each sub-expression can be replaced as (remember i=-1, j=1):
w1 = ((0) && (0)) || ((1) && (1));
w2 = (1) || ((0) && (0)) || (1);
Again, note that j=0 returns 0, changes the value of j to 0 and then later down the line j <= 0 now evaluates to 1.
After the && have been evaluated (their right operand doesn't get evaluated in case the left one is 0), you end up with:
w1 = (0) || (1);
w2 = (1) || (0) || (1);
In the end 1==1.

Check the operator precedence to have a complete view.
In your case you have this order.
First (<,>,<=,>=), then && and finally ||.
So in your example
(I assumed you have a typo in j=0 because you are asking about logical expressions so I changed that to j==0):
i=-1; j=1; // i=-1; j=-i
w1 = (i > 0) && (j < 0) || (i < 0) && (j > 0);
// first we evaluate all the <,>,<=,>=
w1 = false && false || true && true
// Then &&
w1 = false || true
//And finally ||
w1 = true (1)
// With w2 is the same
w2 = (i <= 0) || (j == 0) && (i >= 0) || (j <= 0);
w2 = true || false && false || false
w2= true || false || true
w2= true (1)
// If I donĀ“t change your code, leaving the j=0 as #Lundin commented
w2 = (i <= 0) || (j = 0) && (i >= 0) || (j <= 0);
w2 = true || false && false || true // (j=0 makes j<=0 true )
w2= true || false || true
w2= true (1)
and w1==w2 = true (1)

Regarding the first statement:
w1 = (i > 0) && (j < 0) || (i < 0) && (j > 0);
As logical AND, or &&, has higher precedence than logical OR, or ||, the above statement is equivalent to:
w1 = ((i > 0) && (j < 0)) || ((i < 0) && (j > 0));
Given the values:
i = -1, j = -i;
The statement becomes:
w1 = ((-1 > 0) && (1 < 0)) || ((-1 < 0) && (1 > 0));
Now, in Boolean form:
w1 = ((false) && (false)) || ((true) && (true));
We know that the second operand is not evaluated in logical AND if the first operand evaluates to false. So the statement becomes:
w1 = false || true;
which evaluates to 1.
Regarding the second statement:
w2 = (i <= 0) || (j = 0) && (i >= 0) || (j <= 0);
|
|
w2 = (i <= 0) || ((j = 0) && (i >= 0)) || (j <= 0);
|
|
w2 = (-1 <= 0) || ((j = 0) && (-1 >= 0)) || (0 <= 0);
NB that j = 0 doesn't compare j and 0, it assigns 0 to j.
Now, in Boolean form:
w2 = (true) || ((false) && (false)) || (true);
|
|
w2 = (true) || (false) || (true);
which results in true, and 1 is assigned to w2.

Related

for-loop does not terminate

I'm trying to figure out why my innermost for loop does not break.
I have implemented a Caesar cipher for a "list" of char arrays.
void caesar(char **list, size_t listsize, unsigned int offset) {
for (size_t i = 0; i < listsize; i++) {
for (size_t j = 0; list[i] != NULL && j < sizeof(list[i]); j++) {
for (unsigned int k = 0; k < offset && (list[i][j] >= 65 && list[i][j] <= 90) || (list[i][j] >= 97 && list[i][j] <= 122); k++) {
if(list[i][j] == 122)
list[i][j] = 97;
else if(list[i][j] == 90)
list[i][j] = 65;
else
list[i][j]++;
//works with the break condition
/* if(k == offset - 1)
break;*/
}
}
}
}
So without the last break statement I get an endless loop, even though I have a break condition in the head of my for loop.
Does anybody have an idea?
for (unsigned int k = 0; k < offset && (list[i][j] >= 65 && list[i][j] <= 90) || (list[i][j] >= 97 && list[i][j] <= 122); k++)
Using some placeholder identifiers, the loop condition is written in the form a && b || c, which due to operator precedence is parsed as (a && b) || c and not the a && (b || c) you intend. You can add some parentheses to fix it:
for (unsigned int k = 0; k < offset && ((list[i][j] >= 65 && list[i][j] <= 90) || (list[i][j] >= 97 && list[i][j] <= 122)); k++)
// ^ ^

An error is generated regarding 'lvalue'.what is the reason?

I want to make a program to check if there are any numbers, uppercase and lowercase letters in my password.But,an error about 'lvalue' will occur when this code is executed. What is the reason?
#include <stdio.h>
#include <string.h>
int main(void)
{
char passwd[99];
printf("make a password:");
gets_s(passwd,99);
int num_count = 0, up_count = 0, down_count = 0;
while(1)
{
for (int i = 0; passwd[i] != NULL; i++)
{
if ('0' <= passwd[i] && passwd[i] <= '9')
num_count++;
else if ('a' <= passwd[i] && passwd[i] <= 'z')
{
down_count++;
}
else if ('A' <= passwd[i] && passwd[i] <= 'Z')
{
up_count++;
}
}
if (num_count == 0 || up_count == 0 || down_count = 0)
printf("make the password again!");
else
{
break;
}
}
getch();
return 0;
}
num_count == 0 || up_count == 0 || down_count = 0
should be
num_count == 0 || up_count == 0 || down_count == 0
To explain the error, the statement you have is equivalent to the following:
( num_count == 0 || up_count == 0 || down_count ) = 0
An expression that can be found on the left-hand side of an assignment is called an lvalue, and the expression in parens is not a valid lvalue.

Draw a pattern using for loops in C

Can you guys please help me out here?
I have to print that kind of pattern Example for pattern
in that example the input for the size is 21.
for (int row = 0; row < size; row++)
for (int col = 0; col < size; col++) {
if (row == 0 && col == 0 || row == 0 && col == size - 1 || row == size - 1 && col == 0 || row == size - 1 && col == size - 1)
printf("+");
if ((row == 0 || row == size - 1) && (col > 0 && col < size - 1))
printf("-");
if ((row > 0 && row < size - 1) && (col == 0 || col == size - 1))
printf("|");
if ((row > 0 && row < size - 1) && (col > 0 && col < size - 1)) {
if (row == col)
printf("\\");
else
if (col == size - 2)
printf("/");
else
if (row == x && col == x)
printf("X");
else
printf(" ");
}
}
This is the code i wrote but it is not good .
How can I fix it ?
Thank you!
Here is another solution ,
int main()
{
int size =5;
int counter = 0;
printf("+");
for(int k=1;k<=size+1;k++){
printf("-");
}
printf("+");
printf("\n");
}
for(int i=1;i<=size;i++){
printf("|");
for(int j=1;j<=size;j++){
if(j==0 || j==i )
printf("\\");
else
printf(" ");
if(counter==0){
if(j==size){
printf("/");
counter++;
}
}
else if(j==size-i+1)
printf("/");
if(j==size)
printf("|");
}
printf("\n");
}
printf("+");
for(int k=1;k<=size+1;k++){
printf("-");
}
printf("+");
printf("\n");
return 0;
}
You missed couple of things, read the comments in the code below to check what I corrected.
Here is the working code:
#include <stdio.h>
int main(void)
{
int size = 21;
int x = size / 2; // You want x in the middle so its size / 2;
int i = 1;
for (int row = 0; row < size; row++, i++) // Incrementing 'i' too
{
for (int col = 0; col < size; col++)
{
// In this first if statement below you should put parenthesis around && conditions for better readability and to get rid of any warnings compiler might put out
if ((row == 0 && col == 0) || (row == 0 && col == size - 1) || (row == size - 1 && col == 0) || (row == size - 1 && col == size - 1))
printf("+");
if ((row == 0 || row == size - 1) && (col > 0 && col < size - 1))
printf("-");
if ((row > 0 && row < size - 1) && (col == 0 || col == size - 1))
printf("|");
if ((row > 0 && row < size - 1) && (col > 0 && col < size - 1))
{
if (row == x && col == x) // This should be your first check because in case you are in the middle you want to put 'x' and don't care about rest of the if-else statement
printf("X");
else if (row == col)
printf("\\");
else if (col == size - i) // Instead size - 2, you put here size - i, which is initialized to 1 and incremented by 1 in the outer for loop
printf("/");
else
printf(" ");
}
}
printf("\n"); // You want to print out the new line at the end of every row
}
return 0;
}

search for char sequences in C within a loop

I am trying to find the most efficient way to find tags in a given char array. These "tags" are a sequence of chars located randomly within a char array.
Here is an example: given a char array: {'a','s','s','1','m','s','g','e','x','x','r','s','1',...}. the tag "ss1" indicates the beginning of a message which contains every char until a sequence of "exx" is found, which a tag for the end of the message, and it keeps searching the array for the next sequence of "s1". In this example, the message here is "msg".
my initial design was (pseudo code)
while(array[i] != '\0')
if(array[i] == 's' && array[i+1] == 's' && array[i+2] == '1' )
int j = i+3;
if(array[j] != '\0' && array[j] == 'e' && array[j+1] == 'x' && array[j+2] == 'x' )
i += 3;
else
print(array[j]);
else i++; //next char
may be a little flawed, but you get the idea. Is there a better way? i thought about strstr but since I'm dealing with a char array here and still looping even after deciphering a message, I thought it might be difficult to implement.
Try to maintain a state denoting how much of the tag start and end you have found. Something like this: (This code will work even if the message within the tag is of arbitrary length)
int state = 0;
int found = 0;
int i = 0,j;
int msgStartIndex;
int msgEndIndex;
while(array[i]){
if((array[i] == 's' && state == 0) || (array[i] == 's' && state == 1) || (array[i] == '1' && state == 2) ){
state++;
if(!found && state == 3){
msgStartIndex = i+1;
found = 1;
}
}
else if(!found && (array[i] = 's' && state == 2))
state = 2;
else if(!found)
state = 0;
if((array[i] == 'e' && state == 3) || (array[i] == 'x' && state == 2) || (array[i] == 'x' && state == 1) ){
state--;
if(found && state == 0){
found = 0;
msgEndIndex = i-3;
for(j=msgStartIndex; j < msgEndIndex+1; j++)
printf("%c",array[j]);
printf("\n");
}
}
else if(found && (array[i] == 'e') && (state == 2 || state == 1))
state = 2;
else if(found)
state = 3;
i++;
}
Updated answer for start tag st1 and end tag ex1
int state = 0;
int found = 0;
int i=0,j;
int msgStartIndex;
int msgEndIndex;
while(array[i]){
if((array[i] == 's' && state == 0) || (array[i] == 't' && state == 1) || (array[i] == '1' && state == 2) ){
state++;
if(!found && state == 3){
msgStartIndex = i+1;
found = 1;
}
}
else if(!found && (array[i] = 's' && (state == 1 || state == 2)))
state = 1;
else if(!found)
state = 0;
if((array[i] == 'e' && state == 3) || (array[i] == 'x' && state == 2) || (array[i] == '1' && state == 1) ){
state--;
if(found && state == 0){
found = 0;
msgEndIndex = i-3;
for(j=msgStartIndex; j < msgEndIndex+1; j++)
printf("%c",array[j]);
printf("\n");
}
}
else if(found && (array[i] == 'e') && (state == 2 || state == 1))
state = 2;
else if(found)
state = 3;
i++;

Trouble with moving tiles in Game of Fifteen

Below is a function in the game of fifteen which should search for the "0" tile and once found, allow adjacent tiles to move into its place. It works for the first few moves but then doesn't allow moves that it should permit when the zero tile is at the top row (it starts on the bottom right). Note below the "0" tile is drawn as an underscore. For example:
8 7 6
5 4 3
2 1 _
Tile to move: 3
8 7 6
5 4 _
2 1 3
Tile to move: 6
8 7 _
5 4 6
2 1 3
Tile to move: 7
Illegal move.
Here is the code:
bool move(int tile)
{
int blankrow;
int blankcol;
for (int i = 0; i < d; i++)
{
for (int j = 0; j < d; j++)
{
if (board[i][j] == 0)
{
blankrow = i;
blankcol = j;
}
}
}
for (int i = 0; i < d; i++)
{
for (int j = 0; j < d; j++)
{
if ((board[i][j] == tile) && ((board[i+1][j] == 0 || board[i-1][j] == 0) &&
(board[i][j+1] == 0 || board[i][j-1] == 0)))
{
int swapped = board[i][j];
board[blankrow][blankcol] = swapped;
board[i][j] = 0;
return true;
}
}
}
return false;
}
Just by looking, I'm pretty sure you need to change:
((board[i+1][j] == 0 || board[i-1][j] == 0) &&
(board[i][j+1] == 0 || board[i][j-1] == 0))
To:
(board[i+1][j] == 0 || board[i-1][j] == 0 ||
board[i][j+1] == 0 || board[i][j-1] == 0)
EDIT: I agree with the user comment below. Better code would look something like:
bool move(int tile)
{
int blankrow, blankcol, tilerow, tilecol;
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
if (board[i][j] == 0) {
blankrow = i;
blankcol = j;
}
else if (board[i][j] == tile) {
tilerow = i;
tilecol = j;
}
}
}
if( (blankrow == tilerow && abs(blankcol - tilecol) == 1) ||
(blankcol == tilecol && abs(blankrow - tilerow) == 1) ) {
board[blankrow][blankcol] = board[tilerow][tilecol];
board[tilerow][tilecol] = 0;
return true;
}
return false;
}
You found the blankrow and blankcol. Do the same thing to find the tilerow and tilecol. Then verify either
((blankrow == tilerow) && (abs(blankcol - tilecol) == 1))
or
((blankcol == tilecol) && (abs(blankrow - tilerow) == 1))
Swap if either of those conditions is met. The problem with the existing code is that you can have array accesses out-of-bounds. For example, if i is 0, then board[i-1][j] is an out-of-bounds access.
I think you should change the if statement in the second loop from
if ((board[i][j] == tile) &&
((board[i+1][j] == 0 || board[i-1][j] == 0) &&
(board[i][j+1] == 0 || board[i][j-1] == 0)))
to
if ((board[i][j] == tile) &&
((i+1==blankrow && j==blankcol) ||
(i-1==blankrow && j==blankcol) ||
(i==blankrow && j+1==blankcol) ||
(i==blankrow && j-1==blankcol)))
In the original you are requiring a row offset of one and a column offset of zero and a row offset of zero and a column offset of one simultaneously. Also you're potentially taking a negative index into the array or reading past its end.

Resources