Keep getting warning "Suggest parentheses around '&&' within '||' for C program [duplicate] - c

This question already has answers here:
Why does Clang warn: `'&&' within '||'`?
(2 answers)
Closed 12 months ago.
printf(" 1| %d | %d | %d | %d | %d\n",
((coffee_strength == 'm' || coffee_strength == 'M') &&
(coffee1_type == 'l' || coffee1_type == 'L') ||
(coffee_strength == 'r' || coffee_strength == 'R') &&
(coffee1_type == 'b' || coffee1_type == 'B')),
((coffee_maker == 'r' || coffee_maker == 'R') &&
(coffee1_grindSize == 'c' || coffee1_grindSize == 'C') ||
(coffee_maker == 'C' || coffee_maker == 'c') &&
(coffee1_grindSize == 'f' || coffee1_grindSize == 'F')),
((coffee_servings >= 1) && (coffee_servings <= 4) &&
(coffee1_weight >= 0) && (coffee1_weight <= 250) ||
((coffee_servings >= 1) && (coffee_servings <= 9) &&
(coffee1_weight == 500)) ||
((coffee_servings >= 10) && (coffee1_weight == 1000))),
(((coffee_cream == 'y' || coffee_cream == 'Y') &&
(coffee1_cream == 'y' || coffee1_cream == 'Y') ||
(coffee_cream == 'n' || coffee_cream == 'N') &&
(coffee1_cream == 'n' || coffee1_cream == 'N'))),
((coffee1_temp >= 60.0) && (coffee1_temp <= 69.9) &&
(coffee_maker == 'r' || coffee_maker == 'R') ||
((coffee1_temp >= 70.0) && (coffee_maker == 'c' || coffee_maker == 'C'))));
This is my code that I am trying to compile. Everytime I run it I still get the issue related to bracket placement. I have edited my code many times to try and solve this but the issue still persists. Does anyone have any suggestions as to what I should do?

Operator && has higher precedence than operator ||. Therefore, though legal, the compiler is telling you code that does this:
a && b || c && d
May not be doing what you intended. The compiler will treat that as
(a && b) || (c && d)
but for all it knows, you intended any one of a number of other things.
Perhaps this:
a && (b || (c && d))
or... this:
((a && b) || c) && d
Or maybe... this:
a && (b || c) && d
etc.
It makes a difference, and mistakes like this are common, so although your code will compile, it will do so with warnings when appropriately asked to do so (and it's always appropriate to ask). Not because it is wrong, but rather because you didn't make intent clear enough that the warning monkeys were subdued (which in this case, and most cases, is a good thing) To ensure you get what you expected, the compiler is asking you to clarify your expression via parenthesis. The -Wlogical-op-parentheses, included with -Wall, is the likely candidate telling you this if you're using gcc or clang.
By the looks of it, you've taken up the mantle of trying to address this, but you missed several instances. For example:
((coffee_servings >= 1) && (coffee_servings <= 4) &&
(coffee1_weight >= 0) && (coffee1_weight <= 250) || // <== here
((coffee_servings >= 1) && (coffee_servings <= 9) &&
(coffee1_weight == 500)) ||
((coffee_servings >= 10) && (coffee1_weight == 1000)))
There are others below, which I leave for you to find (they're pretty obvious once you start nesting your parens and realize just how many places a && b || c pops up).
(((coffee_cream == 'y' || coffee_cream == 'Y') &&
(coffee1_cream == 'y' || coffee1_cream == 'Y') ||
(coffee_cream == 'n' || coffee_cream == 'N') &&
(coffee1_cream == 'n' || coffee1_cream == 'N'))),
and here:
((coffee1_temp >= 60.0) && (coffee1_temp <= 69.9) &&
(coffee_maker == 'r' || coffee_maker == 'R') || // <== here
((coffee1_temp >= 70.0) && (coffee_maker == 'c' || coffee_maker == 'C')))

Sorry to say, but that seems like making out everything by looking at space. There are millions of stars, planets, asteroids, comets, meteors.
But I extremely appreciate your effort on formatting. Not a joke.
The problem seems to be here:
&& (coffee1_temp <= 69.9) &&
(coffee_maker == 'r' || coffee_maker == 'R') ||
((coffee1_temp >= 70.0) && (coffee_maker == 'c' || coffee_maker == 'C'))));
Let's expand it:
&& (coffee1_temp <= 69.9) && (coffee_maker == 'r' || coffee_maker == 'R') || ((coffee1_temp >= 70.0) && (coffee_maker == 'c' || coffee_maker == 'C'))));
I am not sure what you want to acheive in that line, but here is a example that might fix the error in that line:
&& (coffee1_temp <= 69.9) && ( (coffee_maker == 'r' || coffee_maker == 'R') || ((coffee1_temp >= 70.0) && (coffee_maker == 'c' || coffee_maker == 'C')) ) ));
Why does the error happen?
You have a a || c && d/a && b || c && d. The compiler warns you since you did not tell it what to do in that situation.
Example:
a && c || c && d,
What should happen first? c || c or a && c or c || c && d, etc... Extremely confusing...
Edit:
It also seems like you have this on many other places too.
You could just use separate if statements to make this clearer...after all it seems like it takes more time to read this than to write a new set of if statements.
Hopefully more readable:
(
(coffee_strength == 'm' || coffee_strength == 'M')
&& (coffee1_type == 'l' || coffee1_type == 'L')
|| (coffee_strength == 'r' || coffee_strength == 'R')
&& (coffee1_type == 'b' || coffee1_type == 'B')
),
(
(coffee_maker == 'r' || coffee_maker == 'R')
&& (coffee1_grindSize == 'c' || coffee1_grindSize == 'C')
|| (coffee_maker == 'C' || coffee_maker == 'c')
&& (coffee1_grindSize == 'f' || coffee1_grindSize == 'F')
),
(
(coffee_servings >= 1)
&& (coffee_servings <= 4)
&& (coffee1_weight >= 0)
&& (coffee1_weight <= 250)
|| (
(coffee_servings >= 1)
&& (coffee_servings <= 9)
&& (coffee1_weight == 500)
)
|| (
(coffee_servings >= 10)
&& (coffee1_weight == 1000)
)
),
(
(
(coffee_cream == 'y' || coffee_cream == 'Y')
&& (coffee1_cream == 'y' || coffee1_cream == 'Y')
|| (coffee_cream == 'n' || coffee_cream == 'N')
&& (coffee1_cream == 'n' || coffee1_cream == 'N')
)
),
(
(coffee1_temp >= 60.0)
&& (coffee1_temp <= 69.9)
&& (coffee_maker == 'r' || coffee_maker == 'R')
|| (
(coffee1_temp >= 70.0)
&& (coffee_maker == 'c' || coffee_maker == 'C')
)
)
Now, is it really hard to make out what the issues are?
Fix, THAT MIGHT NOT BEHAVE AS YOU INTENDED:
(
(
(coffee_strength == 'm' || coffee_strength == 'M')
&& (coffee1_type == 'l' || coffee1_type == 'L')
)
|| (
(coffee_strength == 'r' || coffee_strength == 'R')
&& (coffee1_type == 'b' || coffee1_type == 'B')
)
)
(
(
(coffee_maker == 'r' || coffee_maker == 'R')
&& (coffee1_grindSize == 'c' || coffee1_grindSize == 'C')
)
|| (
(coffee_maker == 'C' || coffee_maker == 'c')
&& (coffee1_grindSize == 'f' || coffee1_grindSize == 'F')
)
)
(
(
(coffee_servings >= 1)
&& (coffee_servings <= 4)
&& (coffee1_weight >= 0)
&& (coffee1_weight <= 250)
)
|| (
(coffee_servings >= 1)
&& (coffee_servings <= 9)
&& (coffee1_weight == 500)
)
|| (
(coffee_servings >= 10)
&& (coffee1_weight == 1000)
)
)
(
(
(
(coffee_cream == 'y' || coffee_cream == 'Y')
&& (coffee1_cream == 'y' || coffee1_cream == 'Y')
)
|| (
(coffee_cream == 'n' || coffee_cream == 'N')
&& (coffee1_cream == 'n' || coffee1_cream == 'N')
)
)
)
(
(
(coffee1_temp >= 60.0)
&& (coffee1_temp <= 69.9)
&& (coffee_maker == 'r' || coffee_maker == 'R')
)
|| (
(coffee1_temp >= 70.0)
&& (coffee_maker == 'c' || coffee_maker == 'C')
)
)
And as #user3386109 said, you can simplify statements checking for uppercase and lowercase like a == 'A' || a == 'a' to toupper(a) == 'A' using toupper(int c) and tolower(int c) from <ctype.h>

Related

Is my negation of this if statement correct?

I am currently working with some legacy code that has this if statement:
if(c == 30 || c == 3 || c == 4 || r == 'Y' || t == 'X' ||( s>= 50000 && s <= 50999))
{
//do nothing
}
else
{
function1();
}
I am trying to eliminate the unnecessary "do nothing" by negating the if, but I'm not sure what to do about the 's' part:
if((c != 30 && c != 3 && c != 4 && r != 'Y' && t != 'X') ...what goes here?...)
{
function1();
}
I've tried both && (s >= 50000 || s <= 50999) and ||(s < 50000 && s > 50999) but those failed the test cases I ran. When I tried &&( s < 50000 || s > 50999)) all my test cases succeeded, but I know I can't test for everything and so I'm hoping someone with a stronger grasp of logical negation can tell me with certainty whether this is correct.
If you have a logical expression like
expr1 || expr2
then its negation
!( expr1 || expr2 )
is equivalent tp
!expr1 && !expr2
And vice versa if you have an expression like this
expr1 && expr2
then its negation
!( expr1 && expr2 )
is equivalent to
!expr1 || !expr2
So to negate this expression
c == 30 || c == 3 || c == 4 || r == 'Y' || t == 'X' ||( s>= 50000 && s <= 50999)
like
!( c == 30 || c == 3 || c == 4 || r == 'Y' || t == 'X' ||( s>= 50000 && s <= 50999))
we will get
!( c == 30 )&& !( c == 3 ) && !( c == 4 ) && !( r == 'Y' ) && !(t == 'X' ) && !( s>= 50000 && s <= 50999)
then
c != 30 && c != 3 && c != 4 && r != 'Y'&& t != 'X' && ( !( s>= 50000 ) || !( s <= 50999))
and at last
c != 30 && c != 3 && c != 4 && r != 'Y'&& t != 'X' && ( s < 50000 || s > 50999 )
This will work. However, it's a little redundant:
if((c != 30 && c != 3 && c != 4 && r != 'Y' && t != 'X') && (s < 50000 || s > 50999))
An easier way would be to just negate the entire statement:
if(!(c == 30 || c == 3 || c == 4 || r == 'Y' || t == 'X' ||( s>= 50000 && s <= 50999)))

CS50 Pset6 error 405 keeps on printing server.c

So my code, no matter what, returns error 405 (once the test that only two spaces are in the request-line is passed). Which makes me believe I have made an error in creating a code to determine that "GET" is in fact the first word. This is all my code leading up to the "check" that the method type is "GET" or any capitalization thereof.
int s;
s=0;
int i=0;
for(int q=0; q<strlen(line); q++)
{
if(line[q] == ' ')
s++;
}
if(s!=2)
{
error(400);
return false;
}
if((line[i] != 'g' || line[i] != 'G') || (line[i+1] != 'e' || line[i+1] != 'E') || (line[i+2] != 't' || line[i+2] != 'T')||
(line[i+3] != ' ' ))
{
error(405);
return false;
}
Any reason this would always return false? I have int i initialized to 0.
Any reason this would always return false?
Reason :
consider the if statement as :
if(expression_1 || expression_2 || expression_3 || expression_4)
//where
//expression_1 is (line[i] != 'g' || line[i] != 'G')
//expression_2 is (line[i] != 'e' || line[i] != 'E')
//expression_3 is (line[i] != 't' || line[i] != 'T')
//expression_4 is (line[i] != ' ')
let's consider line as GET
Now, expression_1 is always evaluated to be true even though line[i] == G because line[i] != 'g' is true. Therefore, (line[i] != 'g' || line[i] != 'G') is true as true || false == true
Now further expressions are not evaluated as || is a lazy operator and it stops evaluation on first true occurrence as true || anything == true
Thus, if block is always entered and false is always returned.
Solution :
Change the if in your code :
if((line[i] != 'g' || line[i] != 'G') || (line[i+1] != 'e' || line[i+1] != 'E') || (line[i+2] != 't' || line[i+2] != 'T') || (line[i+3] != ' ' ))
To the following :
if((line[i] != 'g' && line[i] != 'G') || (line[i+1] != 'e' && line[i+1] != 'E') || (line[i+2] != 't' && line[i+2] != 'T') || (line[i+3] != ' ' ))
Here line[i] != 'g' && line[i] != 'G' gets evaluated to false as true && false == false and further expressions are checked till a true is encountered.
If no true is encountered then if() block is not entered
Further,
As #twalberg has suggested in the comment, it'd be much readable and understandable if you use your if statement as if( !strncasecmp(line, "get ", 3) ) by including the strings.h header file
Know more about strncasemp() function here : click
That comparison makes the code much harder to read. Use the function strncasecmp() (in either string.h or strings.h) instead:
if (strncasecmp(line, "get ", strlen("get ")) != 0) {
// ...
}
This will fix the logic error in that line -- your current comparison will always evaluate true. I would also suggest enabling more compiler warnings, as this is something that any compiler should catch.

tic tac toe in c, trying to determine who wins

Trying to determine who wins in a game of tic tac toe,I am new to programming. Currently getting user has won after only entering 1 X or O input. Inputs must be entered with 2 int, row and coloumn. Any help is greatly appreciated!
#include <stdio.h>
#include <stdlib.h>
void drawBoard(char board[][3])
{
int rows, columns;
for ( rows = 0 ; rows < 3 ; rows++ )
{
for ( columns = 0 ; columns < 3 ; columns++ )
{
if(board[rows][columns]){
printf( "|%c", board[rows][columns] );
}else{
printf("| ");
}
}
printf("|\n");
}
}
int main()
{
char game[3][3]={{0}};
int totalEntry =0,row,column;
char value;
while(totalEntry<=9){
printf("Please choose x or o: ");
scanf("%c",&value);
getchar();
printf("Enter row number: ");
scanf("%d",&row);
getchar();
printf("Enter Column number: ");
scanf("%d",&column);
getchar();
game[row][column] = value;
drawBoard(game);
if((game[0][0] == game[0][1]) && (game[0][1] == game[0][2]) && game[0][0] != 'x')
if((game[1][0] == game[1][1]) && (game[1][1] == game[1][2]) && game[1][0] != 'x')
if((game[2][0] == game[2][1]) && (game[2][1] == game[2][2]) && game[2][0] != 'x')
if((game[0][0] == game[1][0]) && (game[1][0] == game[2][0]) && game[0][0] != 'x')
if((game[0][1] == game[1][1]) && (game[1][1] == game[2][1]) && game[0][1] != 'x')
if((game[0][2] == game[1][2]) && (game[1][2] == game[2][2]) && game[0][2] != 'x')
if((game[0][0] == game[1][1]) && (game[1][1] == game[2][2]) && game[0][0] != 'x')
if((game[2][0] == game[1][1]) && (game[1][1] == game[0][2]) && game[2][0] != 'x')
printf("User x has won!");
if((game[0][0] == game[0][1]) && (game[0][1] == game[0][2]) && game[0][0] != 'o')
if((game[1][0] == game[1][1]) && (game[1][1] == game[1][2]) && game[1][0] != 'o')
if((game[2][0] == game[2][1]) && (game[2][1] == game[2][2]) && game[2][0] != 'o')
if((game[0][0] == game[1][0]) && (game[1][0] == game[2][0]) && game[0][0] != 'o')
if((game[0][1] == game[1][1]) && (game[1][1] == game[2][1]) && game[0][1] != 'o')
if((game[0][2] == game[1][2]) && (game[1][2] == game[2][2]) && game[0][2] != 'o')
if((game[0][0] == game[1][1]) && (game[1][1] == game[2][2]) && game[0][0] != 'o')
if((game[2][0] == game[1][1]) && (game[1][1] == game[0][2]) && game[2][0] != 'o');
printf("User o has won!");
break;
}
return 0;
}
I would have used something like following, using a loop. Note that since the board is initialized to zero, assigning winner to a board position which still has zero means that a winner isn't found even if the test for all equal passes.
//declare this outside the main while-loop:
char winner=0;
for(i=0;i<3 && !winner;i++) {
if(game[i][0]==game[i][1] && game[i][1]==game[i][2])
winner=game[i][0]; // across
else if(game[0][i]==game[1][i] && game[1][i]==game[2][i])
winner=game[0][i]; // down
}
if( !winner && ( game[0][0]==game[1][1] && game[1][1]==game[2][2] ||
game[0][2]==game[1][1] && game[1][1]==game[2][0] ) )
winner = game[1][1]; // diagonal
if(winner) {
printf( "Winner is %c!\n",winner );
break;
}
IckIckIck.
First, it'll make you life much easier (at least for determining the winner), if you use a one-dimenisional array of 9 elements.
Then, write a function which test one possible win and returns true or false.
bool Test(char board[9], char player, int a, int b, int c)
{
return board[a] == player
&& board[b] == player
&& board[c] == player;
}
Then Test(game, 'x', 0,3,6); -- tests of x wins down left side.
The logic in your conditional is incorrect. Imagine the board looks like this. 0 denotes an empty spot.
0 0 0
0 0 x
0 0 0
The statement if((game[0][0] == game[0][1]) && (game[0][1] == game[0][2]) && game[0][0] != 'x') will evaluate to true because game[0][0] is empty game[0][1] is empty and game[0][2] is empty so they are all equal.
Also since game[0][0] is empty, it is not equal to 'x'.
So changing your != to == will help in that regard.

Segmentation Fault When Parsing Char Arrays

I am working on a function that takes a string parameter (actually sending a char array from the main function, but don't think that makes a difference) in C, and parses the string to be stored in a linked list (it is an assignment for school) and am receiving a segmentation fault. I have added strings to be printed throughout the program in order to debug the program, because it relies on an input file, and I do not know how to start gdb with an input option.
This is what my function looks like:
Token * list_head = NULL;
Token * current = NULL;
char line_segment[MAX_PRINT_LINE_LENGTH + 1];
int i, pos = 0; //In the for loop, we do not not to lose the pos in the array
puts("in token.c, beginning segmentation");
/***************************************************************************
* Loop through the possibilites of the first character starting at the
* position located at the pointer (pretty sure this is still easier on the
* memory and logically then enumerating all of the different symbols and
* types of chars that you will see.
**************************************************************************/
for(i=0; line_copy[pos] != '\0';){
if(line_copy[pos] == 'a' || 'b' || 'c' || 'd' || 'e' || 'f' || 'g' ||
'h' || 'i' || 'j' || 'k' || 'l' || 'm' || 'n' ||
'o' || 'p' || 'q' || 'r' || 's' || 't' || 'u' ||
'v' || 'w' || 'x' || 'y' || 'z' || 'A' || 'B' ||
'C' || 'D' || 'E' || 'F' || 'G' || 'H' || 'I' ||
'J' || 'K' || 'L' || 'M' || 'N' || 'O' || 'P' ||
'Q' || 'R' || 'S' || 'T' || 'U' || 'V' || 'W' ||
'X' || 'Y' || 'Z') //Identifier or Rw
do{
line_segment[i] = line_copy[pos];
pos++; i++;
} while(line_copy[pos] == //All letters of alphabet);
else if(line_copy[pos] == '0' || '1' || '2' || '3' || '4' || '5' ||
'6' || '7' || '8' || '9'){ //Number
do{
line_segment[i] = line_copy[pos];
pos++; i++;
} while(line_copy[pos] == '0' || '1' || '2' || '3' || '4' || '5' ||
'6' || '7' || '8' || '9' || 'e');
}
else if(line_copy[pos] == " "){ //No token
line_segment[i] = '\0';
pos++;
}
else if(line_copy[pos] == "'"){ //String
do{ //We want to keep the first apostrophe for make_node
line_segment[i] = line_copy[pos];
pos++; i++;
} while(line_copy[pos] != "'");
pos++; //Don't want to start on the ending ' symbol.
}
else{ //Symbol
line_segment[i] = line_copy[pos];
pos++;
}
puts("line segmented, attempting node");
printf("line segment: %s\n", line_segment);
current = make_node(line_segment);
memset(line_segment, '\0', MAX_PRINT_LINE_LENGTH);
puts("attempting to add node to list");
list_head = add_to_list(list_head, current);
free(current);
puts("node freed");
}
return list_head;
}
if(line_copy[pos] == 'a' || 'b' || 'c' || 'd' || 'e' || 'f' || 'g' ||
'h' || 'i' || 'j' || 'k' || 'l' || 'm' || 'n' ||
'o' || 'p' || 'q' || 'r' || 's' || 't' || 'u' ||
'v' || 'w' || 'x' || 'y' || 'z' || 'A' || 'B' ||
'C' || 'D' || 'E' || 'F' || 'G' || 'H' || 'I' ||
'J' || 'K' || 'L' || 'M' || 'N' || 'O' || 'P' ||
'Q' || 'R' || 'S' || 'T' || 'U' || 'V' || 'W' ||
'X' || 'Y' || 'Z')
You have to follow the actual C syntax. You can't make things up and expect them to work. You are ORing a bunch of letters, which doesn't make any sense.
Try using isalpha() and isdigit()functions from ctype.h.

Shrink my code, Please

I wrote this stupid chunk of code as an answer for a program exercise from the book "c programming a modern approach 2nd E." by K.N.King, namely ch7;ex4.
I couldn't make it does the same thing with less code, so, Can you?
It's just converting alphabetic phone numbers into numeric form, i'm really curious to see a better coding of this..
Thanks..
#include <stdio.h>
void main()
{
char c;
int phone_number;
printf("Enter phone number: ");
while((c = getchar()) != '\n') {
if(c == 'A' || c == 'B' || c == 'C')
printf("2");
if(c == 'D' || c == 'E' || c == 'F')
printf("3");
if(c == 'G' || c == 'H' || c == 'I')
printf("4");
if(c == 'J' || c == 'K' || c == 'L')
printf("5");
if(c == 'M' || c == 'N' || c == 'O')
printf("6");
if(c == 'P' || c == 'R' || c == 'S')
printf("7");
if(c == 'T' || c == 'U' || c == 'V')
printf("8");
if(c == 'W' || c == 'X' || c == 'Y')
printf("9");
if(c == '0')
printf("0");
if(c == '1')
printf("1");
if(c == '2')
printf("2");
if(c == '3')
printf("3");
if(c == '4')
printf("4");
if(c == '5')
printf("5");
if(c == '6')
printf("6");
if(c == '7')
printf("7");
if(c == '8')
printf("8");
if(c == '9')
printf("9");
if(c == '-')
printf("-");
}
printf("\n");
}
We can take advantage of the fact that characters are sequential (not sure if this is standard, but it happens in most representations, anyway)
Let's make a table specifying which number a letter represents. It would look something like
int keynum[26] = {2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
keynum[0] is the number that A maps to, and so on. If we have a character c and we need to get the proper index in keynum we calculate it by c-'A'
Then our main loop would be:
while((c=getchar()) != '\n') {
if (c>='0' && c<='9')
putchar(c);
else if (c >= 'A' && c <= 'Z')
putchar('0' + keynum[c-'A'])
/* else error? */
}
2 + ((c-'A') / 3) (integral division) is the number you print for A-Y (if 'A'<=c && c<='O'!)

Resources