If statement giving parenthesis error in my triangle exercise - c++

Learning C++ and doing a basic triangle exercise.
Can anyone check my code if I done everything right and explain why I am getting this error: suggest parenthesis around ‘&&’ within ‘||’
#include <iostream>
int main()
{
// enter 3 numbers for sides of triangle
int a, b, c;
std::cout << "Input three numbers: " << std::endl;
std::cin >> a;
std::cin >> b;
std::cin >> c;
// check what kind of traingle it is and output result
if(a == b && b == c){
std::cout << "You have an equalateral triangle." << std::endl;
}else if(a == b && b !=c || a!=b && b==c || a==c && b!=c){
std::cout << "You have an iso triangle." << std::endl;
}else{
std::cout << "You have an scalene triangle." << std::endl;
}
}

The Error Messages you're receiving are a diagnostic that Clang can generate
If these are showing up as errors, you likely have -Werror enabled in your compiler options. You can remove that flag to stop promoting Warnings to Errors. Or, if you don't want it to issue warnings (promoted to errors) for what is (let's be honest) a pretty spurious diagnostic, you can add -Wno-logical-op-parentheses to the compiler options.
As to why this diagnostic is being generated in the first place: The Operator Precedence between && and || is not always obvious, especially to newer programmers, and Clang is suggesting you expressly specify the operator precendence to make sure that what you've written is what you intend. So it's asking you to rewrite these lines like this:
if(a == b && b == c) {
std::cout << "You have an equalateral triangle." << std::endl;
} else if((a == b && b != c) || (a != b && b == c) || (a == c && b != c)) {
std::cout << "You have an iso triangle." << std::endl;
} else {
std::cout << "You have an scalene triangle." << std::endl;
}
The extra parenthesis make the warning go away.
As far as I can tell there isn't actually a logical error in your code (the boolean logic behaves as you expect it to), and indeed, if you were to send this code to a different compiler, they compile it without issue. So this is really just a particular quirk of Clang.

The compiler is suggesting that you use parentheses to make your second if statement clearer/easier to parse.
In particular, you should group the && statements within the || statement using parentheses. That is, change this code
(a == b && b !=c || a != b && b == c || a == c && b != c)
to
((a == b && b != c) || (a != b && b == c) || (a == c && b != c))
It's worth noting that this is a "style error"; the first form is not strictly incorrect code (indeed I was able to compile and run it just fine in the absence of compiler flags), but it's good practice to write it the second way.
If you pass the -Wall flag to your compiler (or more specifically in this case, the -Wlogical-op-parentheses flag) this will show up as a warning. Passing -Werror changes these warnings to errors, which seems to be the case here. It's good practice to use both -Wall and -Werror, since the compiler will then point out potential clarity problems like this and force you to fix them before continuing the compilation.

This is sure to divide opinion, but I am of the ilk that you need to know the C++ grammar well before you attempt to push any code in production.
The fact remains that || has lower precedence than &&. And that should be as second nature to you as the precedence of the binary operators + and * ought to be. Emphasising the obvious with parentheses introduces noise and makes your code harder to read. I'd advise you to switch off that specific warning, and press on.
Note in your particular case though the second conditional simplifies to
else if (a == b || a == c || b == c)
as you have already eliminated the equilateral possibility. Again, some software houses insist that if statements are all mutually excusive in the sense that they can be arbitrarily reordered without the code breaking. Yet more opinion I'm afraid.

Related

C++ test exercise, variables negative conditional

The teacher said that whenever the c variable is negative then: "the variable a is negative", but this doesn't make sense.
Is the program written in the wrong form?
In my opinion else should be part of the if(a>0) with {}. I don t know why he chose to not use it.
In conclusion, is the correct form like: if(a>0){...}else and than cout?
#include <iostream>`
using namespace std;
int main(void) {
int a, b, c;
cin >> a;
cin >> b;
cin >> c;
if (a > 0)
if (b > 0)
if (c > 0)
cout << "they are all positive";
else
cout << "the number a is negative";
}
Your teacher is correct. else applies to the newest if, so the value of c determines the output. (More specifically, the program will only print something when both a and b are positive.) You can test this by running the program.
The output "the number a is negative" is illogical, because that's the point of the test. The program is intentionally written incorrectly. If answers to all test questions were obvious, everybody would get the best grade.
You need to use curly brackets otherwise else will only apply to the newest if. The program will only print when both a and b are positive.
The core problem here is the lack of a clear specification of what the program is supposed to do. I suspect that you do have it, but without it available here I can only explain what the code is doing and how the quote from the teacher can be read as describing what the code does.
To visualise here is a modified version of your code, which is self-explaining (I hope):
#include <iostream>
using namespace std;
int main(void) {
int a, b, c;
cin >> a;
cin >> b;
cin >> c;
if (a > 0)
if (b > 0)
if (c > 0)
cout << "they are all positive"; // true
else
cout << "the number 'c' is negative or zero, 'a' and 'b' are positive";
else
cout << "the number 'b' is negative or zero , 'a' is positive, no idea about 'c'";
else
cout << "the number 'a' is negative or zero , no idea about 'b' and 'c'";
}
I suspect that where this outputs "no idea" is where you might want to use more ifs, in order to describe the other numbers.
Note: I stuck to your style (without {}). But I recommend to use them generously. In my experience it makes life easier and in my opinion makes code more readable.
I think the quote from the teacher
whenever the c value is negative it say: " the a number is negative" but it doesn't make sense
Should be read as:
'Whenever the c value is negative (and the other two are positive) this code outputs: "the 'a' number is negative", but that doesn't make sense, because a is in fact positive when this output occurs.
And I agree.

What is proper way to use the curly arrow in C++?

Consider:
for(int i = 10; b >= i; i++){
if(i%2 == 0)
cout << "even" << endl;
else
cout << "odd" << endl;
}
for(int i = 10; b >= i; i++){
if(i%2 == 0){
cout << "even" << endl;
}else{
cout << "odd" << endl;
}
}
Both of these code work with the only difference being the curly brackets for the if else statement. When should I use curly brackets and when not?
They're called braces or curly brackets, not to be confused with the "curly arrow" in some languages, ~>.
In C, and by inheritance C++, these are optional on single-line if statements, but as many, many bugs have been created by omitting them you'd be advised to use them as a matter of principle even when they're redundant.
That is a mistake like this is easy to overlook:
if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
goto fail;
goto fail;
Where it seems like that goto is conditional, yet it's not, it just drops through. This is the huge OpenSSL bug that caught everyone by surprise, and if veteran developers can mess it up, so can you.
The second form is the most reliable, least ambiguous, especially when formatted according to typical conventions:
for (int i = 10 ; b >= i;i++) {
if (i%2 == 0) {
cout << "even" << endl;
}
else {
cout << "odd" << endl;
}
}
for is a statement, not a function, so the syntax is for (...) with a space. Functions have no space, like f(...). Omitting the space implies for is a function, which it absolutely is not. The same goes for if, while and so on.
It's worth noting that the original code can actually be reduced to:
for (int i = 10 ; b >= i;i++)
if (i%2 == 0)
cout << "even" << endl;
else
cout << "odd" << endl;
Since that if is a single statement, even with the else clause attached.
Again, this is not advised because the rules of what is and isn't a single statement can be confusing.
Google has a detailed C++ style guide that may help you. In particular, it says that
In general, curly braces are not required for single-line statements, but they are allowed if you like them; conditional or loop statements with complex conditions or statements may be more readable with curly braces. Some projects require that an if must always have an accompanying brace.
If the 'if', 'else' or 'for' structures have only one statement inside them, you can decide not to use the curly brackets. However, I would recommend to use them in order to improve the code readability.

Explanation of this C++ code I learned in college

I'm a newbie here and I just started college. We are learning C++ and I find it a little bit difficult, because of the way the teachers explain.
Yesterday we did a task that says to create a program, which finds greatest common divisor of 2 numbers. So, the teacher started writing the code, but the explanation wasn't enough for me and I really need some help right now.
(I putted comments on the things I don't understand.)
Here is the code:
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int a, b;
cout << "a = ";
cin >> a;
cout << "b = ";
cin >> b;
cout << "GCD (" << a << ", " << b << ") is ";
if (a != 0 && b != 0){
size_t min = abs(a) < abs(b) ? abs(a) : abs(b); //What's that after (?)?
size_t max = abs(a) > abs(b) ? abs(a) : abs(b);
size_t diff = max - min; //What is that variable used for?
while (diff > 0)
{
min = diff < min ? diff : min;
max = diff > min ? diff : min;
diff = max - min;
}
cout << min << endl;
}
else{
if (a != 0 || b != 0)
cout << (a>b ? a : b) << endl;
else
cout << "not possible!!!\n";
}
system("pause");
return 0;
}
QUESTION: When should I put {} on if's, while's etc.?
This is the syntax for an if-statement
if ( condition ) statement-true else statement-false
statement-true is either one statement or a block of statements in {...}
So you can use if without {...} if there is only one line. But it is better to always use {...}.
It is necessary when you need more that one line/statement to be executed by the if/else/while. Valid examples:
if (a != 0 || b != 0)
cout << (a>b ? a : b) << endl;
if (a != 0 || b != 0) cout << (a>b ? a : b) << endl;
if (a != 0 || b != 0) {
cout << (a>b ? a : b) << endl;
a++; }
If you did:
if (a != 0 || b != 0)
cout << (a>b ? a : b) << endl;
a++;
The the a++; would be executed regardless of the if condition.
Some programmers like to use {} even for single statements because they believe it leads to more usable and maintainable code. I do not belong to that group but I can see the arguments on either side.
size_t min = abs(a) < abs(b) ? abs(a) : abs(b); //What's that after (?)?
C and C++ have a construct that is similar to an if-else statement. This line basically says that if abs(a) is smaller than abs(b), then min should take the value of abs(a); otherwise, it should take the value of abs(b).
size_t diff = max - min; //What is that variable used for?
It's not clear what you mean here. If you mean diff, the code essentially uses it in the subsequent while loop to perform division by repeated subtraction. This is a very strange thing to do, especially because it is so inefficient, and division would have been more compact and efficient in the loop. It's even stranger given that earlier the author uses ?: (which you asked about); that construction is used mainly because it's more compact and efficient than an if-else statement, but this is rather strange code, anyway.
When should I put {} on if's, while's etc.?
You should do it by default. You don't have to do it if only one statement is to be performed when the condition is true (resp. false) but people usually do as a matter of good style and to assist readability. For instance, this code
if (a != 0 || b != 0)
cout << (a>b ? a : b) << endl;
else
cout << "not possible!!!\n";
could just as easily be
if (a != 0 || b != 0) {
cout << (a>b ? a : b) << endl;
} else {
cout << "not possible!!!\n";
}
...and a lot of instructors would actually require the latter from learners.
In addition to the other answers:
//What's that after (?)?
foo ? bar : qux;
Is the use of the ternary operator.
If foo is true the expression evaluates to bar else it evaluates to qux.
Just adding my two cents...
This
if (a != 0 || b != 0)
cout << (a>b ? a : b) << endl;
is equivalent to
if (a != 0 || b != 0) {
cout << (a>b ? a : b) << endl;
}
The big difference comes when you realize that code is not something static that you write once and then never change again. Lets change the example a little bit (intentially weird intendation)
if ( x ) // (I)
y = a;
z = b;
is not the same as
if ( x ) { // (II)
y = a;
z = b;
}
Using brackets allows you to focus on only the part you care about. Consider that you later decide to swap the two lines, then
if ( x ) {
z = b;
y = a;
}
is still ok (its the same as (II), apart from swapping the two instructions), while
if ( x )
z = b;
y = a;
is doing something completely different as the version above (I). If you use the brackets you dont need to care whether those two lines are inside a if block. To decide if you can swap them you need to look at nothing more than those two lines. This is not the case if you do not use the brackets. This may seem like a minor thing, though I have seen countless bugs caused by not putting brackets where there could be some.
For 1 line of code following if, else, else if, while, etc
if (<some condition>)
//1 line of code`
and
if (<some condition>)
{
//1 line of code
}
...are equivalent and it is up to you (personal style,developer choice,readability etc.) to make that decision.
For > 1 line of code following if, else, else if, while, etc
{} is required if you want code completely scoped to the condition statement. It is up to you the developer to make sure to scope these lines of code (i.e. the compiler will not warn you about this.. it will not know if the intent was 1 line or multiple lines).
So an example
if(<some condition>)
{
//line of code 1
//line of code 2
}
the compiler will let you do this...
if(<some condition>)
// line of code 1
// line of code 2
but //line of code 2 has no relation to the if condition since it was not scoped with {} and will be executed regardless of the if statement condition.

Would this do the same?

just reading through some C++ books and I'm just wondering if somebody could double check this, would these two pieces of code, both do the same?
if (x > 5)
if(y > 5)
cout << "something";
else
cout <<"something else";
if (x > 5) && (y > 5)
cout <<"something";
else
cout <<"something else";
Am I right in thinking these two both do the same thing just differently written, one friend told me they were another told me they weren't so just thought best ask here
Thanks.
These two statements are not the same. The former prints nothing at all if x <= 5.
The first example also has incorrect indentation (and is a great argument for why you should always include braces). The equivalent with braces is
if (x > 5) {
if (y > 5) {
cout << "something";
} else {
cout <<"something else";
}
}
This should make it obvious that if x <= 5 it executes nothing.
They do not.
Consider the sample data of x=y=0.
The first snippet will print nothing, while the second one will print "something else".

C++ if statements using strings not working as intended

I have searched for this error but noone seems to be having the same problem as me. I am trying to make a basic text based RPG game in C++ to learn, and I want the user to be able to type what they want to do, for example if they type ATTACK they will attack the monster, but my if statement:
if((current_move == "ATTACK") || (current_move == "attack"))
returns false!
Here is the full function below:
while(monster_health > 0)
{
std::cin >> current_move;
std::cout << current_move;
if((current_move == "ATTACK") || (current_move == "attack"))
{
std::cout << "You attacked the monster!\n";
double damage = return_level(xp) * 1.2;
std::cout << "You did " << damage << " damage!\n";
monster_health -= damage;
if(monster_health < 0)
{
monster_health = 0;
break_out = true;
}
}
else if(current_move == "FLEE")
{
std::cout << "You ran away...\n";
break_out = true;
}
else
{
std::cout << "Sorry, I didn't understand, what will you do? ATTACK or FLEE?\n";
}
}
I just keep getting "Sorry, I didn't understand" message;
Please let me know of any other errors or bad practises as I've only just started learning :)
What's the type of current_move? If it's char* (or char[]), you are comparing pointers, not strings. Better use std::string for current_move, then the comparison with == will work intuitively.
You need to add #include <string>. (In MSVC certain parts of strings also work without that, but it's nonstandard and leads to errors e.g. when passing strings to cout).
If you're using a C string (char[]), you need to use strcmp() to compare it. If the two strings are equivalent, it will return 0.
if (strcmp(current_move, "ATTACK") == 0) will return true if they match.
You need to do current_move==string("attack") otherwise you will be comparing pointers. String operator == or strncmp, either one or the other...
Your problem is that you are comparing C strings. When you do == on them, you are comparing the pointer of the two, which in this code is useless to do.
My suggestion would be to just change the type of current_move to std::string and it will just work. Then you will be comparing the contents, not the pointers.