String comparing to constant with if-else statement. Skipping second if/else - c++

I seem to be running into an issue. While trying to get input based off of A.M./P.M. entry,my if else statement is having some sort of logic error. I've never really done this sort of thing (I'm a bit new to c++) so help would be appreciated.
cout << "What time was the dose administered? (Round to hour): ";
cin >> time;
cout << "A.M./P.M.? ";
cin >> ap;
cout << ap;
if (ap == "A.M.", "am"){
ap = "A.M.";
}
else if (ap == "P.M.", "pm"){
ap = "P.M.";
}
else { cout << "This is not a valid entry.";
}
"ap" is a string.
No matter what is entered, the result is "A.M."
Side note: Originally, it would only print "P.M." but both statements were orignally "if", when I changed it to "if else" it began printing "A.M." only.

This...
ap == "A.M.", "am"
...under the rules of operator precedence, is equivalent to...
"am"
...which in a boolean context undergoes standard conversion to true (via a non-0 pointer).
That's because the comma operator evaluates the sub-expression on its left - namely ap == "A.M." - and while any side-effects of that evaluation are enacted the actual value of the sub-expression is then discarded and the sub-expression on the right - namely "am" - is evaluated and used instead.
You should instead use:
if (ap == "A.M." || ap == "am")
(The C++ Standard allows the keyword "or" as an alternative to ||, but famously Microsoft's compiler doesn't support it without an extra command-line argument, so in practice it's best avoided for portable code.)

Related

Why the compiler is showing true?

The output should be false, as false&&true is false. However, the compiler is giving 1 as output.
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int b = 13;
bool flag = true;
cout << ((b - 4) < a) && !flag;
return 0;
}
This is because << has higher precedence than &&, your expression should be:
cout << (((b-4)<a) && !flag);
A more detailed explanation:
One of the first things that any C++ compiler does when processing your source code is to construct an abstract syntax tree (AST) representing your source code. The AST is a tree structure that encodes -among other things- the precedence of different unary and binary operators. An AST for the expression you have written (cout << ((b - 4) < a) && !flag;) would look something like this:
&&
/ \
<< !
/ \ \
cout < flag
/ \
- a
/ \
b 4
How do we know that e.g. && must be the root of the AST or that sub-expressions in parentheses are evaluated first? Because the C++ operator precedence rules say so. These are similar to the rules we use when doing math on paper (e.g. do multiplication before addition) but extended to all operators supported by the language.
We can use the AST to see in what order the sub-expressions of this expression are evaluated, the general rule being that evaluation happens in "bottom up" order, i.e. from the leaves to the root of the AST. In this particular case, evaluation could (conceptually) happen like this:
// left subtree
b - 4 = 9
9 < a = true
cout << true = cout (operator<< returns a reference to cout)
// right subtree
!flag = false
And finally we're left with cout && false. cout implements operator bool which allows it to be implicitly cast to bool, yielding true if the stream has no errors. Because that is the case here, we finally have true && false == false the value of which is unused.
So you can see that your program outputs 1 because during evaluation of the left subtree, cout << true is executed. Afterwards, cout && !flag, though well formed, essentially does nothing because it has no side effects and you don't use the result.

Is 'If Else' statement indentation important or not in C++? [duplicate]

This question already has answers here:
If statements without brackets
(3 answers)
Closed 10 months ago.
Does the indentation in an if else statement have any bearing on the execution of the code or is it just something to do for cleaner code?
Example from the book Accelerated C++ written by Andrew Koening:
while(c != cols) {
if(r == pad + 1 && c == pad + 1) {
cout << greet;
c += greet.size();
} else {
if(r == 0 || r == rows - 1 || c == 0 || c == cols - 1)
cout << "*";
else
cout << " ";
++c;
}
}
The prefix increment of c is executed regardless of whether r=0 or not, but I don’t understand why.
If the if statement turns true, an asterisk is printed. If not, a blank space is printed and c is incremented.
That’s how I am reading it, but c gets incremented regardless of what the values of r or c are.
This is what it says in the book, but there isn’t any explanation I could find:
Notice how the different indentation of
++c;
draws attention to the fact that it is executed regardless of whether we are in the
border.
Whitespace does not affect C++ runtime behavior. (Unlike certain other languages, like Python).
I should mention that in your else block, you do not use braces. So, only the first statement (cout << " ";) will be part of the else clause. The subsequent ++c; will execute regardless of the value of r and c.
Note that this last point is subjective, so take it with a grain of salt... As you can see, when braces are omitted from if ... else ... blocks, there is potential for confusion. Some would argue that it leads to more concise code, but many (including myself) would argue that you should always use braces. This is especially important when you work on a large team because code tends to grow over time. I've seen many cases in production code where an if statement was missing the braces and someone added a second line to the if clause without remembering to add braces. This didn't work as expected and caused wasted time debugging fails, just because the braces were omitted.
Both C and C++ are not affected by white space in their interpretation of the code. That does not mean the programmer should not care about its misuse.
The best way to illustrate what the above code actually represents is to explicitly define all of the inferred braces as below. Note that the if statement that had no braces only has one line of code affected by the 'if then' or 'else' clause.
This is one of the reasons that people try to insist on
'good coding practices' to ensure that other people are able to clearly interpret the flow and intent of the programmer.
while(c != cols) {
if(r == pad + 1 && c == pad + 1) {
cout << greet;
c += greet.size();
} else {
if(r == 0 || r == rows - 1 || c == 0 || c == cols - 1) {
cout << "*";
} else {
cout << " ";
}
++c;
}
}
In C++ the length of indentation does not affect the interpretation of the statements. Sometimes whitespace is needed to separate characters, e.g., in int a. Other times it is not needed, e.g. in a=b+c;.
The if statement is defined that after the condition if(condition) can only be one statement.
If we want more statements we have to group them with braces {...}
Unlike Python, C++ does not care about indentation.
But your else applies only on the first line. To apply to a block, it should be within { }
else
{
cout << " ";
++c;
}
Indentation is not your problem here.

How to write one line and nested 'if' statement without '?:' (is it possible?)

Is it possible to write a one line if-else statement (i.e. only using one ;) without using the ?: expression? For instance something of the form:
if (p == 1) " " else "\n";
Potential purpose could be:
cout << if (p == 1) " " else "\n";
Just curious if this is possible, don't know if there are any practical applications for this.
Thanks
You're asking "how do I do X, without using any of the tools the language provides to do X". It's silly.
And the answer's no. It's not possible.
This doesn't address the general question, but it does work for the specific example you provided.
std::cout << " \n"[(bool)(p - 1)];
Explanation:
First, a string literal (such as " \n") is an array. As such, it participates in pointer decay, and can be indexed just like any other pointer or array.
Second, an integer can be converted to a bool, and the conversion has the special property that a zero is converted to false, and anything else is converted to true. So when I subtract 1 from p, then convert it to bool, it is false if p is 1, and true otherwise.
Third, a bool can be (implicitly) converted back to an integer. false converts to 0, and true converts to 1. So converting from an int to a bool and back has the result that a 0 stays a 0, and anything else becomes a 1.
So, with those three points taken into consideration, the expression:
" \n"[(bool)(p - 1)]
results in one of these two possibilities:
" \n"[0] // a space (if p == 1)
" \n"[1] // or a newline (if p != 1)
I'd downvote this answer if I could.
You already used the two important words that are key to undestand why what you intend is not possible, but you probably haven't grasped their full meaning: Statement and expression.
The if statement (like all statements) does not yield a value, while the ?: operator is an expression that does yield a value.
Distinguishing between statements and expressions is a fundamental concept that is worth learning (check out the links in this answer and take your time!), not just for C++ but for almost all programming languages.
cout << [=]{ if (p == 1) return " "; else return "\n"; }();
Basically: no, it's not possible to do this:
cout << if (p == 1) " " else "\n";
That is exactly the purpose of ?: operator - it yields value. Some things may not be possible with if-else syntax. Example: conditional initialization. Consider:
if(p == 1)
int value = 1; //local variable!
else
int value = 0; //and so is this one!
//here 'value' is unknown
Above problem could be solved this way:
int value; //default initialization
if(p == 1)
value = 1; //assignment to already initialized variable!
else
value = 0; //and so is this!
But these two are not equal. For some types, it may result in totally different behavior, because initialization is different from assignment. ?: is a solution:
int value == (p == 1) ? 1 : 0; //'value' is initialized with value, that depends on 'p'
Do not try to do things without tools, that were designed to do that things for you.

Nested if else, which one is it out of the options:

How is this called :
if else
if and if else
if or if else
if
none of the above
There is an if-else and an if :
if (n > 0) {
if ((n % 3) == 0) {
cout << "The number is positive and divisible by 3\n";
}
}
else {
cout << "The number is zero or negative \n";
}
//continue...
So looking at the possible answers, it's either the second one or the last one, depending if the order of the english text matters or not. The wording is unfortunate and ambiguous
Reasoning by elimination brings us to the same conclusions:
It definitively can't be just if nor if-else as there are 3 different branches with different outcomes.
It can't be if or if-else, because the two conditions in the diagramme are in cascade. This means clearly that the outcome depends of the two conditions (and), and not just one (or).
Edit: But if I'd have to answer in an exam, I'd say second answer because I see an if { and if } else : the ambguity of the english sentence gives me the right to understand that the else of the if and if else could be associated with the first if an not necessarily the second.
The graphic represents an if-else and an if. They do not appear in that particular order in the list of answers, so I would choose if and if else only if that answer is allowed to be ambiguous and the order is not important, otherwise I would choose none of the above instead.
If anyone needs to know this here it is :
IF AND IF ELSE
Why? Because when a new if statement comes after an if statement is true then it's called if and if else.
Otherwise if there was a new if statement on the left side where it's false it would be if or if else.
Thank you all.

I didn't program my while loop correctly

printf("What do you do?\n1. Walk Away.\n2. Jump.\n3. Open Door.\n\n");
scanf("%d",&Choice);
printf("\n\n\n");
while(4<=Choice,Choice<=0);
{
printf("That is not a choice.\n");
printf("What do you do?\n1. Walk Away.\n2. Jump.\n3. Open Door.\n\n");
scanf("%d",&Choice);
printf("\n\n\n");
}
So this is my program. It works but what I want it to do is to repeat until an answer of 1, 2, or 3 is put in. But no matter what the answer is it has it go through the while loop then continue regardless of the next choice. (Also, I did declare "Choice"; I just didn't want to show the whole program.)
There are two problems in your code. Your while-loop expression is incorrect. The comma does not do what you think it does: in C/C++, the comma executes the left-hand expression and evaluates to the right-hand expression, meaning that in your case you are only checking the second condition. You probably want:
while(4<=Choice || Choice<=0)
The || is the OR operator, which returns true if either of the expressions around it are true.
Secondarily, there is a misplaced semicolon at the end of the while loop:
while(4<=Choice,Choice<=0); //<-- this should not be here
This marks the end of the loop, meaning that your code is parsed as:
while(4<=Choice,Choice<=0); //loop body is empty
{
//and we have a random unnamed block following it
}
Remove the semicolon and your while loop should execute correctly.
C and C++ have a comma operator, which has the lowest precedence of all operators. It evaluates the left operand and throws the result away, and then evaluates the right operand. Thus, your while condition is equivalent to:
while (Choice <= 0)
You also have a bug because there is a semicolon immediately after the condition, which makes for an infinite loop if Choice is not strictly positive (because nothing in the loop changes the value of Choice).
What you probably intended to write was:
while (Choice >= 4 || Choice <= 0)
{
...
}
The comma operator , doesn't test both conditions, it simply returns the second of the two. So your while loop is the equivalent of:
while(Choice<=0) ;
and since there's a ; following the statement, it is in fact an infinite loop if the condition is met. Good thing you didn't enter a choice of -1.