Can you explain HOW bool can control loops? - c++

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

Related

My C++ file expected a 'while' in place of an if. And at the end it expected a '('

I have recently started to program in C++ and i wrote a simple file to try and test. It converts Celsius to Fahrenheit and vice versa. It keeps giving me an error about expecting a 'while', and a '('
As i said I'm new to this and really don't know what to try. I've moved the if else and else onto the same line as the ending curly brace, of the former if/if else statement.
#include <iostream>
int main()
{
int f;
int c;
char choice;
ask:do {
std::cout << "Hello welcome! Would you like to convert from C to F (a) or F to C (b)?\n";
std::cin >> choice;
}
if (choice == "a") { // that if before this comment has squiggly red line
std::cout << "Great, What is the temperature in Celcius? (No decimals please)\n";
std::cin >> c;
f = (c * 1.8) + 32;
std::cout << "The temp in Farenheight is " << f << "degrees\n";
}
if else (choice == "b") {
std::cout << "Great, What is the temperature in Celcius? (No decimals please)\n";
std::cin >> c;
c = (f / 1.8) - 32;
std::cout << "The temp in Celsius is " << c << "degrees\n";
}
else {
std::cout << "Sorry that wasn't an option. Please try again.";
goto ask;
}
} // this also is squiggly
I would like it to output the number of c to f vice versa, but it wont run and it says:
expected a 'while' 18 ,5
expected a '(' 42 ,1
The code here has a syntax error:
do {
std::cout << "Hello welcome! Would you like to convert from C to F (a) or F to C (b)?\n";
std::cin >> choice;
}
The do keyword needs to be paired with a while, as the loop is do ... while rather than just do. So, for example, you might say something like
do {
std::cout << "Hello welcome! Would you like to convert from C to F (a) or F to C (b)?\n";
std::cin >> choice;
} while (!isValidInput(choice));
where isValidInput would be some helper function that validates the input.
So in other words, the issue isn't that you can't use an if statement here as much as your do ... while loop is incomplete.
There are some other syntax errors here as well. For example, you can't say if else, though else if is perfectly fine. Another issue: in C++, double-quotes are used for strings while single-quotes are used for characters, so comparisons of the form choice == "b" won't compile, because you're comparing a char and a string. Those errors will likely surface after you fix the aforementioned one.
As a final note, while goto is indeed legal in C++, it's generally frowned upon in favor of other options like regular styles of loop. If you follow the above approach of having your loop continue until you get a valid input, then you should be able to eliminate the goto that takes you back to the point where you ask for input.
Hope this helps!
The do is a loop in c++. Specifically it is part of the do … while loop. It expects you to clarify how long the loop should be executed until the condition is met (and the do... while loop is different from while loop in that it executes the code at least once no matter what).
A ///
Your do is not enclosing your entire program in curly braces, so if you're not trying to loop your entire program then you may not need do at all. Simply make it
std::cout << "Hello welcome! Would you like to convert from C to F (a) or F to C (b)?\n";
std::cin >> choice;
B ///
If you want to loop the entire program the curly braces after do must capture everything and be finished with a while. In this scenario you can remove your goto statement; this answer can explain why you may want to avoid this What is wrong with using goto?.
E.g.
bool loop = true;
do {
// your program
} while (loop); // this will loop while "loop" variable continues to be true
You can then have a condition in your loop somewhere that changes loop = false to break the loop, for example asking the user if they want to continue or not.
///
Some other things I noticed about your code:
char is assigned values with ' and note ".
if else is not correct, instead it is else if (…

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 anyone explain the logic behind this simple logic? I'm lost

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.

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.

Confusion about correct design of a program C++

I made a small program that generates primes and lets the user check a number and see if it's a prime or not. Problem is, I'm not sure how to properly design it. This is the program:
#include <iostream>
#include <vector>
typedef unsigned long long bigint;
std::vector<bool> sieve(size_t size)
{
std::vector<bool> primelist(size);
primelist[0] = false;
primelist[1] = false;
for (bigint i = 2; i < size; ++i) { primelist[i] = true; }
for (bigint i = 2; i * i < size; ++i)
{
if (primelist[i])
{
for (bigint j = i; j * i < size; ++j)
primelist[i*j] = false;
}
}
return primelist;
}
int main()
{
bigint range;
bigint number;
std::vector<bool> primes;
std::cout << "Enter range: " << std::endl;
std::cin >> range;
primes = sieve(range);
while (1)
{
std::cout << "Enter number to check: " << std::endl;
std::cin >> number;
if (primes[number])
std::cout << "Prime" << std::endl;
else
std::cout << "Not prime" << std::endl;
}
return 0;
}
The basic flow I want to achieve is: Input range, /handle input/, input number to check, /handle input/
I also want to give the user an option to change the range at any given time, by writing a command like "change range number"
I have a few problems with this:
I want the program to be under control if the user inputs a range bigger than unsigned long long, and if the user basically exceeds any limit(like for example if the range he input was 100 then if he checks for 101) an exception will be caught. I know this needs to be implemented using try/catch/throw, but I have no idea how to do that while keeping the option to change the range and without making my code spaghetti code.
Also, I want the errors to be of enum type(I read that enums are good for exceptions), something like
enum errors
{
OUT_OF_RANGE = 1, //Out of the range specified by the user
INCORRECT_VALUE, //If user input "one" instead of 1
RANGE_SIGNED, //If user inputs a signed value for range
NUM_LIMITS //Number exceeds unsigned long long
};
I have no idea how to use exception handling, not to mention using it with enums. How the hell do I keep this program safe and running, while keeping away from spaghetti code?
I am extremely confused. If someone could help me design this program correctly and maintain readability and efficiency, it will really improve my future program designs.
Thanks for reading!
You asked a lot.
You want to validate user input. Users should not be able to enter huge numbers, non-integers, and so on.
I'm going to start off by answering that this is absolutely not a scenario that exceptions should be used for. Exceptions are used to handle exceptional circumstances. These are ones you can't anticipate or really deal with.
A user enters a number that's too big? You can handle that. Tell them that their number is too big, please enter a number between 1 and X.
A user enters the word apple? You can handle that. Tell them that they can only enter integers.
One way of doing this would be to make a ValidateInput function. You can have it return a number (or an enum, they're basically the same thing) to tell you whether there was an error.
In order to do the validation, you will most likely have to receive input as an std::string and then validate it before turning it into a number. Getting input as an unsigned int or similar integral type doesn't really allow you to check for errors.
This adds a bit of work, since you need to manually validate the input manually. There are libraries with functions to help with this, such as boost::lexical_cast, but that's probably too much for you right now.
Below is some very basic psuedo code to illustrate what I mean. It's only meant to give you an idea of what to do, it won't compile or do the work for you. You could extend it further by making a generic function that returns a message based on an error code and so on.
enum error_code {
SUCCESS, // No error
OUT_OF_RANGE, // Out of the range specified by the user
INCORRECT_VALUE, // If user input "one" instead of 1
RANGE_SIGNED, // If user inputs a signed value for range
NUM_LIMITS // Number exceeds unsigned long long
};
// This function will check if the input is valid.
// If it's not valid, it will return an error code to explain why it's invalid.
error_code ValidateInput(const std::string& input) {
// Check if input is too large for an unsigned long long
if (InputIsTooLarge)
return NUM_LIMITS;
// Check if input is negative
if (InputIsNegative)
return RANGE_SIGNED;
// Check if input is not an integer
if (InputIsNotInteger)
return INCORRECT_VALUE;
// If we make it here, no problems were found, input is okay.
return SUCCESS;
}
unsigned long long GetInput() {
// Get the user's input
std::string input;
std::cin >> input;
// Check if the input is valid
error_code inputError = ValidateInput(input);
// If input is not valid, explain the problem to the user.
if (inputError != SUCCESS) {
if (inputError == NUM_LIMITS) {
std::cout << "That number is too big, please enter a number between "
"1 and X." << std::endl;
}
else if (inputError == RANGE_SIGNED) {
std::cout << "Please enter a positive number." << std::endl;
}
else if (inputError == INCORRECT_VALUE) {
std::cout << "Please enter an integer." << std::endl;
}
else {
std::cout << "Invalid input, please try again." << std::endl;
}
// Ask for input again
return GetInput();
}
// If ValidateInput returned SUCCESS, the input is okay.
// We can turn it into an integer and return it.
else {
return TurnStringIntoBigInt(input);
}
}
int main() {
// Get the input from the user
unsigned long long number = GetInput();
// Do something with the input
}
I like Dauphic's answer, particularly because it illustrates breaking down the problem into bits and solving them individually. I would, however, do GetInput a bit differently:
unsigned long long GetInput() {
// Get the user's input
std::string input;
error_code inputError;
// Repeatedly read input until it is valid
do {
std::cin >> input;
inputError = ValidateInput(input);
if (inputError == NUM_LIMITS) {
std::cout << "That number is too big, please enter a number between "
"1 and X." << std::endl;
}
// ...handle all other cases similarly
} while(inputError != SUCCESS);
// If ValidateInput returned SUCCESS, the input is okay.
// We can turn it into an integer and return it.
return TurnStringIntoBigInt(input);
}
The recursive solution is nice, but has the drawback of, well, being recursive and growing the stack. Probably that's not a big deal in this case, but it is something to watch out for.
As for how to write ValidateInput, basically you're going to be scanning the string for invalid characters and if none are found, testing if the value will fit in your chosen integer type until reading it into a variable with e.g. >>.
note: this solution has a serious flaw in that it doesn't check the state of std::cin. If the user were to pass EOF, i.e. press ^D, the program would get stuck in the loop, which is not good behavior.
Instead of a vector of bool you'd better use a bitset
With that, you can use the Eratosthene method to determine if a number is prime or not.