Can anyone explain the logic behind this simple logic? I'm lost - c++

I was just trying out the do while loop in C++, while I came up with an idea of having the descriptions, or whatever it's called, within the brackets after the while in a do while loop do multiple things.
So here's my initial logic: I have an already set up password variable and an input variable. If the two things match, then it would get out of the loop and output "correct password", else wise it would keep going back to the loop, output "wrong password" and so it goes on. Here's my code:
// do while
#include<iostream>
using namespace std;
int main(){
int input, password=19960819;
do{
cout << "Type your password:" ;
cin >> input;
}while(input!=password && cout << "wrong password" << endl);
cout << "correct password" << endl;
return 0;
}
I was expecting that even though I had the correct answer inputted, I would still have it output "wrong password". I thought that cout << "wrong password" << endl part would always return as true, which should also be executed no matter how, and that the only factor would be the input!=password part. However, the results were actually perfect, which wasn't what I was expecting... Can anyone explain the logic? I was challenging myself to not use if or other logic, but simply using the do while logic to reach this result, but I don't get the reason why it's working now...

C++ uses short-circuit evaluation for built-in1 boolean operators, meaning that when you do:
A && B
B is evaluated only if A is true, because if A is false, the whole expression is false (whatever the value of B).
So in:
input != password && cout << "wrong password" << endl
When input != password is false (when you enter the correct password), the second operand cout << "wrong password" << endl is not evaluated, and thus nothing is outputed.
Extra details on the evaluation of the conditions:
The type of input != password is bool;
The type of cout << "..." << endl is std::ostream&;
A std::ostream is convertible to bool either directly (since C++11) or using the conversion to void* (C++03).
Since there is no operator&&(bool, [const] std::ostream&) and std::ostream is convertible to bool, the built-in operator&&(bool, bool) is used here, so short-circuit evaluation applies2.
When input != password is true (you entered a wrong password), cout << "..." << endl is evaluated, and then converted to a bool value, which will by true most of the time3, thus allowing the loop to continue.
When input != password is false, short-circuit prevents cout << "..." << endl from being evaluated, and nothing is sent to the output.
1 For overloaded operators, short-circuit evaluation no longer applies. See http://en.cppreference.com/w/cpp/language/operator_logical.
2 You could add a user-defined overload for && before main, e.g. bool operator&&(bool b, std::ostream &s) { return b && (bool)s; }, to see that short-circuit only applies for built-in operator.
3 There is no guarantee that this returns true, since the stream could be in a failure state, but this is unlikely with std::cout.

cout << "wrong password" << endl always evaluates to true (via a conversion to bool operator) and has the side effect of outputting that text.
But that is only evaluated if input != password, due to the short-circutting nature of &&.
It's rather cute, really. Personally though, I'd write
} while (input != password && std::cout << "wrong password\n");
Note that this is reliant on std::basic_ios::operator bool which has changed subtly from C++11. See http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool. In many ways it's better to avoid flashy code like this.

This is because && and || are evaluated in short-circuit. So, for example, A && B would evaluate true if both (and only both) A and B are true, but (and here is the short-circuit) it would be false if A or B is false, so when A is false, there is no need to evaluate B.
In your scenario, when the comparaisson 'input!=password' is false (i.e. input == password), it stops evaluating the expression.
Hope this helps :)
Sorry for my english.

Related

Does this actually ensure that a number is between 1-9?

int position = 0;
void set_position() {
std::cout << "Player " << player << "'s Turn (Enter 1-9): ";
while (!(std::cin >> position)) {
std::cout << "Player " << player << ", please enter a valid number between 1 and 9: ";
std::cin.clear();
std::cin.ignore();
}
std::cout << "\n";
while (board[position-1] != " ") {
std::cout << "Oops, there's already something in that position!\n\n";
std::cout << "Player " << player << "'s Turn (Enter 1-9): ";
std::cin >> position;
std::cout << "\n";
}
}
This is a solution to a tic tac toe challenge in Codecademy and I would like to understand if the function while (!std::cin >> position)) actually checks if it is 1 to 9. Position is just an int, declared as int position = 0;. How does this actually check if it's 1 through 9? Or does it just check if it's an integer? So far Codecademy's C++ course seems to be pretty bad and doesn't go through that much.
Too Long Didn't Read (TLDR)
That code only filters out non-numbers.
Explanation:
To help you understand, lets look at what actually happens inside
while(!(std::cin >> position))
On the inside of all that lies std::cin >> position. >> is the "extraction operator", so we're going to extract something from std::cin (standard input). Using the >> operator really just turns around and calls operator>>() on the given object. The given object in this case is a std::istream. It's operator>>() call signature looks like:
istream& operator>> (int& val)
It returns an istream (itself), and takes a reference to an int, position in your case.
So if we evaluate std::cin >> position mentally (or in a debugger, which is much better: zero guesswork), we'll see that we've returned that istream (which is almost certainly a return *this; at the end of the function).
Now lets replace std::cin >> position with the effective return value std::cin and see what the code looks like.
while(!(std::cin))
Okay, so we need to apply the ! operator to the istream named cin. "Wait what?!" you cry... Any class/struct can define a variety of different operators, such as <<, >>, =, ==, >, <, !, *, ->... there's a bunch of them. The relevant one is the ! operator, with the following function signature and documentation:
bool operator!() const
Returns true if either failbit or badbit is set, and false otherwise. This is equivalent to calling member fail.
Incidentally, the const on the end means "we promise not to change the object running the function". This allows the compiler to make various optimizations, knowing the object's state won't change. It also lets our fellow programmers know what sorts of things are happening (and not happening) inside the function.
We'd expect that this would return true (fail or bad was set) when you type a non-digit into operator>>(int&), and we'd be right. Cheers to the library designers for following the "Principle of Least Surprise".
The return of value of operator!() is then passed into the while loop. So if someone types a letter or punctuation or what have you, they'll see the error message and have to type again.
Conclusion:
This doesn't do anything for filtering out numbers outside of 1-9, it just filters out non-numbers. You'd need new code for that, such as the suggestion in the comment by #Eljay.

Why giving an invalid expression to a variable whose data type doesn't comply with the expression, returns my switch's default case's statement? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm a beginner in coding, in general, and as an academic student, I, along with my colleagues, started learning C++ first in our first year.
I was given an assignment to write a simple calculator using the aforementioned language. And while I could work through it using the 'switch' method, I still have a problem with my program:
#include <iostream>
using namespace std;
int main() {
char z;
double x,y,a,b,c,d;
cout << "Enter two operands, and an operator: ";
cin >> x >> y >> z;
a = x + y;
b = x-y;
c = x /y;
d = x * y;
switch (z) {
case '+':
cout << "The result is: " << a << endl;
break;
case '-':
cout << "The result is: " << b << endl;
break;
case '/':
cout << "The result is: " << c << endl;
break;
case '*':
cout << "The result is: " << d << endl;
break;
default:
cout << "Your operator is good! \n";
}
return 0;
}
In execution, after the first 'cout' statement appears, I tried entering an 'operator' or any other character; assigning it to the 'x' variable and expecting to get an error due to assigning a character to a 'double'-type variable (x). However, this didn't happen and doing so returned my switch's default statement instead.
Why did that happen?
where is my error?
In execution, after the first 'cout' statement appears, I tried
entering an 'operator' or any other character; assigning it to the 'x'
variable and expecting to get an error due to assigning a character to
a 'double'-type variable (x).
Not sure how to put it in a nice way... Your expectations are wrong! If you do something wrong in your code then you dont get a nice candy error message that told you what went wrong. If you do something wrong then wrong things will happen. For user input that means: You have to actively check if the input suceeded. If you dont then you risk bad things to happen (read about undefined behaviour if you dont know what it is).
here you go
That being said, in some sense there actually is what you were expecting. From cppreference:
If extraction fails (e.g. if a letter was entered where a digit is
expected), value is left unmodified and failbit is set. (until C++11)
If extraction fails, zero is written to value and failbit is set. If
extraction results in the value too large or too small to fit in
value, std::numeric_limits::max() or std::numeric_limits::min()
is written and failbit flag is set.
So when the user enters "operator", then the extraction fails because "operator" is not a double. You can catch such wrong input by inspecting the failbit flag. Long story short: streams can convert to bools, if the result is true the input was succesful:
double x = 0.0;
std::cin >> x;
if (std::cin) std::cout << x;
else {
std::cout << "input failed";
std::cin.clear(); // reset error state flags
// and ignore characters left in the stream
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
conclusion
Maybe in one place you want to throw an exception in case of wrong input (see here for an example), while in a different place the input may fail silently and performance is a concern. C++ philosophy is: You do not pay for what you do not need. It takes some effort to get user input right. However, if you use the tools given to you, you can easily detect wrong input and act accordingly.
Last but not least, always do initialize your variables! Only since C++11 you can be sure that x will have a value after std::cin >> x;. (Even after C++11 you should initialize it.)
TL;DR
Why did that happen?
If you are compiling "pre C++11" then your code has undefined behaviour (x is used uninitialized here: a = x + y;). Since C++11 the reason is simply that z is not any of the other characters +,-... but \0 (cin reads one character and then fails, not only x but also all the other input operations fail).

Can you explain HOW bool can control loops?

I'm a beginner programmer in C++ (currently), and I've got a conceptual question.
I'm trying to filter a cin input to ensure that it is a one-or-two-digit integer between 01-04, and if it isn't, to produce an error and ask for a new input.
I'm also using map to give the user a list of options that, upon valid selection, routes inputs (integers) through any of several methods to produce a relevant result, but I'll ask a more specific version of this question elsewhere.
I found a snippet of code at http://www.cplusplus.com/forum/beginner/26821/ that is meant to validate an input. I sort of get it, except where the boolean condition is set inside the while loop. Because I don't understand it, it makes it very difficult to edit or make sure that I'm manipulating it right.
Here is the example code:
int main()
{
int num;
bool valid = false;
while (!valid)
{
valid = true; //Assume the cin will be an integer.
cout << "Enter an integer value: " << endl;
cin >> num;
if(cin.fail()) //cin.fail() checks to see if the value in the cin
//stream is the correct type, if not it returns true,
//false otherwise.
{
cin.clear(); //This corrects the stream.
cin.ignore(); //This skips the left over stream data.
cout << "Please enter an Integer only." << endl;
valid = false; //The cin was not an integer so try again.
}
}
cout << "You entered: " << num << endl;
system("PAUSE");
return 0;
And here is my code (the entire thing, to give context). I don't think it's complete, I just want to make sure I'm using the boolean right.
float _tmain(float argc, _TCHAR* argv[])
{
bool validInput = !true;
map<string,int> Operations;
Operations.insert(pair<string, int>("Addition", 01));
Operations.insert(pair<string, int>("Subtraction", 02));
Operations.insert(pair<string, int>("Multiplication", 03));
Operations.insert(pair<string, int>("Division", 04));
cout << "Welcome to OneOpCalc, what operation would you like to perform?" << endl;
for(map<string, int>::iterator ii=Operations.begin(); ii!=Operations.end(); ++ii)
{
cout << (*ii).second << ": " << (*ii).first << endl;
}
while (!validInput)
{
cin >> operatorSelection;
if (cin.fail() || operatorSelection < 4 || operatorSelection > 1)
{
cout << "Error: Invalid selection. Please choose a valid number." << endl << endl;
cin.clear();
cin.ignore();
}
}
}
Does while (!valid) mean "While valid is false"? In my head, it's saying "While valid is !valid", which obviously, would always be false.
EDIT: Thanks for the answers guys, I'm looking through them all. One answer I keep getting goes too general; I understand that ! is NOT, and I understand the concept of flipping the bool using it. However the implicit logical implications are what confuse me. In any given statement, I am used to thinking of !valid as a way of flipping the valid value; Not testing a condition. It's the syntax of using it to test a condition that tricks me. In other words, writing while(!valid) reads literally to me as while(NOTvalid), not while(valid==false). I can't get myself to understand why in this case, !valid reads as a condition and not just a bit-flip.
Loops (and ifs) are controled by an expression of type bool.
In while ( !valid ), the expression is !valid, the operator
not applied to the value of the variable valid.
while ( !valid ) means (literally) while the expression
!valid (which means "not valid") is true.
For the rest, the code you're copying is pretty bad. I wouldn't
use it as an example if I were you.
As for your own code:
_tmain is very particular to Microsoft. You don't want to
use it. If your writing a console application, just use main.
(Same thing holds for _TCHAR, rather than char.)
Neither _tmain nor main can return a float. The return
type of main should always be int. I'm less familiar with
_tmain, but it's either int or void. (Probably int, if
you're in a console mode program.)
!true is false. Always. (Programming is different than
the real world. There are no maybes.) Why be more
complicated than necessary?
There's no need for the flag variable at all. You
can just write:
cin >> operatorSelection;
while ( !cin || operatorSelection > 4 || operatorSelection < 1 ) {
// ...
}
In case of error, you currently only ignore a single
character. You probably want to ignore up to and including the
end of line.
(std::cin.ignore( std::numeric_limits<std::streamsize>::max() );.
And the condition in your if will always be true. (See my
version above.) Where do you expect to find a number which is
neither less than for nor greater than one?
In your code, inside the loop, just add:
else
validInput = true;
after the if closing bracket.
You want to get out of it once the user has typed a correct value.
You want to run the loop "while there is not a valid input". Remove the non-bold words, and translate to C++.
Of course, the second case is not working, because nothing changes validInput inside the loop, so it stays "invalid", and the loop continues forever (And if you want to set something to false then bool validInput = !true; is more convoluted than bool validInput = false; - the compiler will do the same thing, but someone reading the code will have to think to see what it does - it is a good thing to think when reading code, but it's not a good thing to write code that is more complicated than necessary...).
A while loop has a condition and a body, the body is executed as long as the condition evaluates to true.
From the C++ standard:
6.5.1 The while statement
In the while statement the substatement is executed repeatedly until the value of the condition (6.4) becomes
false. The test takes place before each execution of the substatement.
A while loop can have one of the following forms
while ( condition ) statement
while ( condition )
{
statement(s)
}
The ! operator is a logical not and this is how you should read it: while not valid. You could have also written that as:
while(valid == false)
or
while(valid != true)
Note that here, again, != is equivalent to not equal.
nijansen forgot to add the most elegant one
while(!valid)
which is the same as the 2 others

string operations and odd results

first post so my apologies if I break protocol.
I'm working on a silly program for school and I have the following code.
cout << "//Dictionary Program//\n\n";
cout << "Enter a command:\n's' - to search for a pattern at the beginning\n";
cout << "'e' - to search for a pattern at the end\n";
cout << "'c' - to search for a pattern anywhere in the word\n";
//Gather user input.
cout << "Please enter a command ('q' to quit): ";
cin >> userCommand;
cmdCheck = userCommand.find("secq");
while(cmdCheck < 0 || userCommand.length() > 1){
cout << "Please enter a valid command\n";
cin >> userCommand;
cmdCheck = userCommand.find("secq");
}
This is driving a menu and I am trying to validate the input. It should be one letter, and one of the following "secq"
I am having a terrible time with the string.find() in the immediate window. I end up with CXX0047: Error: argument list does not match a function. Which I don't understand at all because I am using it elsewhere.
The while condition is not being nice to me. When I give the program a "v" it ends up inside the block like it should, but then I give it an "s" where the cmdCheck should evaluate to 0, but it gives a -1 and stays inside the block.
Lastly, I coded around another error with the cmdCheck but I had that in the while condition and it was not working either. while(userCommand.find("secq") < 0 ...
My inital thought was a problem with the input buffer but when I look at the userCmd variable in the Locals window I have a character array of size 1. There is only the letter and no junk from the buffer (as far as I can tell)
I know I could just tie a bunch of || together with each command but this is a bit more elegant in my opinion. I looked at my final last year and my conditionals were ugly. It's more of a matter of principle at this point.
The expression userCommand.find("secq") tries to find the string "secq" in userCommand. From the sounds of it, you actually want to do the exact opposite, i.e., find the userCommand in the string "secq":
std::string::size_type cmdCheck = std::string("secq").find(userCommand);
while (cmdCheck == std::string::npos) {
...
}
Also note that std::string doesn't return an int. Instead it returns a std::string::size_type. This may be a typedef for int but it may also be a typedef for a different integer type. If the string being passed to find() can't be found, std::string::npos is returned. The exact value for this constant is also not defined so you are best off comparing to this constant instead of making any assumptions.
I'm guessing that userCommand is an std::string. Since the command is supposed to be a single character, use a char instead of a string. Then just use the value as the argument in a switch statement, with appropriate cases for the valid characters and a default case that gives an error message.
Take input using getline in a string.
getline (cin, userCommand) ;
If the input is one letter, take it in a single char. If you insist on taking it in a string, use its first index to check.
Maybe a loop like this would be more appropriate:
char result;
std::cout << "Your command: ";
for (std::string line; ; )
{
if (!(std::getline(std::cin, line))
{
std::cerr << "Fatal error: Unexpected end of input!\n";
std::exit(1);
}
if (line.size() == 1 && line.find_first_of("secq") == 0)
{
result = line[0];
break;
}
std::cout << "Sorry, I did not understand. Please say again: ";
}
std::cout << "Thank you! You said, '" << result << "'\n";
Now if the loop breaks, result will contain the user input.

c++ logical alternative operator

During work over a simple project I have found situation that I don't fully understand. Consider following code:
#include <iostream>
using namespace std;
bool test(int k)
{
cout << "start " << k << endl;
bool result; // it is important that result's value is opposite to initial value of recheck in main()
result = false;
return result;
}
int main()
{
bool recheck;
recheck = true;
for (int i = 2; i > -1; i--)
{
recheck = (recheck || test(i)); // (1)
cout << i << " ???" <<endl;
}
cout << "----------------------------" << endl;
cout << endl;
recheck = true;
for (int i = 2; i > -1; i--)
{
recheck = (test(i) || recheck); //different order that in (1)
cout << i << "???" <<endl;
}
return 0;
}
It returns completely different results from for loops:
2 ???
1 ???
0 ???
----------------------------
start 2
2???
start 1
1???
start 0
0???
It seems that it first one test(int k) is not even invoked. I suspect it has something to do with || operator. Could anybody explain such a behavior?
The built-in || short-circuits: if the left operand is true, the right operand is not evaluated (it doesn't matter what the value of the right operand is, because the value of the || expression is guaranteed to be true in this case).
For completeness, but not particularly relevant to the question: In c++, the || operator is overloadable, just as many other operators are. If an overload is used, short circuiting does not take place.
The boolean operators || and && will short-circuit when one of the operands - evaluating from left-to-right - can determine the result of the expression, without reference to the remaining operands.
In the case of ||, this means that if the first operand is true, the remaining operands aren't evaluated, because the result of the entire expression will always be true.
In the first loop, the variable recheck - that is local to main - is always true, and so the function call test never needs to be evaluated: it is skipped, and you see no output.
In the second loop, the test function call is evaluated first, and it's result can only be determined after calling the function, so the function is called on each iteration, and you see the output.
Your comment says:
it is important that result's value is opposite to initial value of recheck in main()
Your test() function currently can't see the value of recheck, which is local to main().
Assuming your comment reflects your intent, you need to pass recheck as a parameter to test(); you can then use the unary ! operator, something like:
result = ! recheck;
And of course you need to fix the logic in main() so that test() is called when you need it to be.
Your requirements aren't clear enough for me to comment further.
Others have addressed the specific issue that you have raised. Just a note to say that beware of using multiple question marks in a row. Trigraph sequences start with two '??' characters and the third character after two question marks is interpreted differently.