My switch case is supposed to be within the while loop, but it is having complications. I want the loop to end when the user inputs 1,2, or 3, while continuing to loop if any other value.
#include <iostream>
using namespace std;
int main() {
int k = 0;
enum CompanyRole {EXECUTIVE = 1, MANAGER = 2, STAFF = 3};
cin >> k;
while((k != 1) || (k!=2) || (k!=3)){
switch(k)
{
case EXECUTIVE:
cout << "Executive\n";
break;
case MANAGER:
cout << "Manager\n";
break;
case STAFF:
cout << "Staff\n";
break;
default:
cout << "Wrong role. Enter again.\n";
cin >> k;
break;
}
std::cin >> k;
}
return 0;
}
Here whenever you have suppose value for k is 1 there is one conditional statement which evaluates to true and enters the loop. (This will also hold for k=2 or k=3).
It will be while((k != 1) && (k!=2) && (k!=3)). Think this way, earlier you were saying - you will continue to the loop if either of them is true. Because in c++ if either of the condition is true - the whole expression evaluates to true - which basically make the loop iteration.
Here by putting those && we are ensuring that it is not one of 1 ,2 or 3. That is what you wanted to achieve.
The condition satisfying which the control enters the loop is those very conditions which are taken into account in switch. Solution:- Redesign the code - more explicitly, put the switch cases after the while statetment. Make sure you understand what each component does and redesign.
I'd rewrite your code to look like this:
while((k != 1) && (k!=2) && (k!=3)){
std::cout << "Wrong role. Enter again.\n";
std::cin >> k;
}
switch(k) {
// same as before
}
Your while is acting as a trap for valid input, so you don't need to test for good input in there. Let the while naturally exit once you have a valid value for k, then operate on k. It also avoids a few other small issues in your code.
Since the loop is performed at least once, you should use a do-while instead of a while loop. A do-while loop is always performed at least once, so the test to see whether you exit the loop is done at the bottom, not at the top.
In addition to that, you could simply introduce a bool variable and set it to false if the input is "bad". This makes the code much easier to vision and to follow.
Example:
#include <iostream>
using namespace std;
int main()
{
int k = 0;
enum CompanyRole { EXECUTIVE = 1, MANAGER = 2, STAFF = 3 };
bool ok;
do
{
ok = true; // assume input is good
cin >> k; // get the input
switch (k)
{
case EXECUTIVE:
cout << "Executive\n";
break;
case MANAGER:
cout << "Manager\n";
break;
case STAFF:
cout << "Staff\n";
break;
default:
ok = false; // input is bad.
cout << "Wrong role. Enter again.\n";
break;
}
} while (!ok); // if input is bad, loop again
}
At the top of the loop, we assume the input is good (ok = true;), and if it's bad, set ok to false. Then the test is for ok being false.
The above is much easier to follow, no having to deal with getting logical and and or erroneously stated, basically not too much thinking is involved. If the input is "bad", just indicate it's bad and test for it.
Related
I have a while loop and I want to skip the whole loop without running the condition in parantheses again becuse as you now, the vector's Size is one greater then their cell number. I mean it is like:
[ Cell 0 ][ Cell 1 ][ Cell 2] --> Size = 3
So I have to skip the whole loop to prevent an Error. I need to write something that takes the program from point A to B without running "while()" My loop:
size = 0;
while ((usernamelog[size] != usrlog || passwordlog[size] != passlog) && size < usernamelog.size())//Checking Username And Password
{
if (x == 2)//Login Unsuccessfull
cout << "Username or Password is Incorrect. Please try again." << endl;
cout << "Enter Your Username: ";
cin >> usrlog;
cout << "Enter Your Password: ";
cin >> passlog;
x = 2;
size++;
if (usernamelog.size() == size)
//Point A
}
//Point B
for example, when usernamelog.size is 2 and size is 2, Jump From A to B
You are looking for break :
After this statement the control is transferred to the statement immediately following the enclosing loop or switch. As with any block exit, all automatic storage objects declared in enclosing compound statement or in the condition of a loop/switch are destroyed, in reverse order of construction, before the execution of the first line following the enclosing loop.
Example:
while (true) {
std::cout << "this loop runs only once";
break;
}
There is an "issue" that comes up sometimes when you have nested loops, so I'll also add it here even not relevant for your code at the moment. Note that break only breaks out of the most inner loop. Once you have more loops you need more than a single break. For example this will run till infinity:
while (true) {
while (true) {
break;
}
}
An easy solution is to put the loops inside a function and to return:
void foo() {
while (true) {
while (true) {
std::cout << "this will be printed only once";
return;
}
}
}
Note that you can do this also for a single loop and often that is the cleaner way.
PS: If you do know the number of iterations beforehand, then it is more idomatic to use a for loop instead. Also consider to fix your conditions such that you do not need to break out of the loop from within the body.
quick question.
How would I get this code to loop itself so that it keeps asking the question, but still allow a different action when a non-numeric input is given?
int main()
{
int temp = 0;
while (temp =1, 10)
{
int amend_numb = -1;
cout << "\nWhich amendment? ";
cin >> amend_numb;
if (amend_numb == 1)
{
cout << "a.\n";
}
if (amend_numb == 2)
{
cout << "b.\n";
}
I attempted to put it into this while statement, however if I enter anything other than an integer into the cin, then it does an infinite loop of constantly repeating the cout statement. Is there any way to get rid of this problem?
while (temp =1, 10)
Although the expression is syntactically correct, it may not perform the way you think:
1. Assign temp to 1.
2. Disregard the value returned from the assignment (because of comma operator)
3. Remaining expression is 10, which is nonzero, so loop continues.
The general rule of thumb is to use a for loop for known quantities of iterations:
for (temp = 1; // assignment
temp < 10; // continuation expression
++temp) // iterator incrementing
{
// loop content
}
When interacting with Users, you want the loop to repeat until an exit condition is satisfied.
unsigned int temp = 0;
while (temp != 0)
{
cout << "Enter amendment number, 0 to quit: ";
cin >> temp;
if (temp > 0)
{
switch (temp)
{
//...
}
}
}
Some people like a forever loop with a break statement:
unsigned int temp = 0;
while (true)
{
cout << "Enter amendment number, 0 to quit: ";
cin >> temp;
if (temp == 0)
{
break; // terminate loop
}
switch(temp)
{
//...
}
}
while (true)
{
//your code
}
simple
and then for your none integer input, you should really do a type cast if you think the user might not provide expected input. Since cin would return a string so you should use string to int cast, something like "stoi" if your compiler supports it or look up c++ string to int I am pretty sure you will get bunch answers.
Edit: if the user might enter anything that is not a number, then you better check for error, put a try and catch statement between the cast, if it fails then tell the user input is not valid.
When the condition is true or false, how can I make it return back and ask the question again, making the user re-enter the value?
Here is what I want to implement:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int n;
cout<<"Enter numbers. Press 5 to stop: ";
cin>>n;
bool tr=true;
while(tr)
{
if(n!=5)
cout<<"You entered "<<n; //How to make it return again, since its false? I keep getting infinite loops :( ;
else
tr=false;
}
return 0;
}
You need to prompt the user in the while loop, so that it occurs in each iteration:
int n;
bool tr = true;
while(tr)
{
cout << "Enter numbers. Press 5 to stop: ";
cin >> n;
if(n!=5) {
cout << "You entered " << n;
} else {
tr = false;
}
}
Just put all your code (except 'n' and 'tr' definition) in while loop as follow:
int main()
{
int n;
bool tr=true;
while(tr)
{
cout<<"Enter numbers. Press 5 to stop: ";
cin>>n;
if(n!=5)
cout<<"You entered "<<n;
else
tr=false;
}
return 0;
}
The other answers all work, and there is something to be learned about improving program flow from them, but I believe the trick you're asking for is the continue keyword, which skips the remainder of this iteration of the loop.
bool tr = true;
int n;
while (tr)
{
cout << "Enter numbers...";
cin >> n;
if (n != 5)
continue;
else
tr = false;
}
EDIT Part 1: On the continue keyword.
You want to make your code as readable as possible. In this example, its use is unnecessary (as the other posters have shown); but it is the answer to the question "How do I skip the rest of processing in this iteration of my loop and continue to the next iteration?". Usually, such flow-breaking directives actually make code harder to read; but sometimes the opposite is true. Anything (or, at least, almost anything) that can be accomplished with continue or break, can be accomplished without them, so if you're going to use them, you want to have a definite reason for doing so. Usually, when I use continue, it's because I'm looping through a collection of inputs and I want to skip processing the loop whenever the input isn't in the format I'm expecting. Something like this (pseudo-code)...
foreach (Input i in ReceivedInputs)
{
if (i.isBad())
{
cout << "Bad input";
continue;
}
// Do massive block of calculating here.
}
is easier to read than this...
foreach (Input i in ReceivedInputs)
{
if (i.isBad())
cout << "Bad input";
else
{
// Do massive block of calculating here.
}
}
because the second version makes it harder to track what scope you're in, if you're looking toward the end of the massive block of calculating. In this case, I gain code readability by continue, so I use it. But simple code probably shouldn't use it. The break keyword is similar, though it's a lot easier to come up with examples where break is beneficial.
EDIT Part 2: On multiple iterations
This is just an issue of setting up the loop; there are no magic keywords here. The shortest way I can come up with, is probably something like this:
int n = 0;
int numberToTake = 10;
for ( int numbersTaken = 0; numbersTaken < numberToTake; ++numbersTaken)
{
cout << "Enter numbers...";
int n = 0;
for (cin >> n; n != 5; cin >> n)
cout << "Try again.";
// Do whatever processing on n you want to do here.
}
Though I should point out that, doing it this way, the only value you will ever get from the user will be 5, and if he inputs anything that doesn't fit in an integer, you will get unexpected behavior.
EDIT 3: After reading the comment more thoroughly, I think you're just looking for is the more traditional use of the for loop.
No need for the exra bool variable.
The idiom can be: Infinitely loop until the user enters 5:
for(;;) { // Loops infinitely
cout << "Enter numbers. Press 5 to stop: ";
cin >> n;
if(n == 5)
break; // Exits the loop
cout << "You entered " << n; // Before the if if you want to print 5 as well
}
I need to implement a loop where I have to ask the user, and then check the validity of the input (in this case it is necessary to print that is an invalid number). What is the better way to implement it?
Our programming professor does not let us use break, and for(;;) since, as he says, it is a bad practice. Is that correct?
Example 1:
int i = 0;
while(i == 0) {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
}
Example 2:
int i = 0;
do {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
} while (i == 0) // Better while(true) and use break ?
Example 3:
int i = 0;
for ( ;; ) {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
else
break;
}
In your case the second construct (do..while) is the most intuititve for the reader to look at what the code does, and this is important.
The first one isn't so bad, the last one is poor a "for" construct is usually used where there are a limited number of iterations with the limit set in advance. It doesn't have to be, but intuitively that is how a for loop is used.
(Incidentally if the user entered a string that isn't a number you would have to clear the fail flag on cin, but that is not really the question being asked here).
Don't you need to accept zero as an integer? It's good practice to not rely on input numbers having a special meaning.
If the meaning of the loop is to loop infinitely until the task is done there's nothing wrong with clearly saying while(true). I would probably do something more like this (requires C++11): (or use boost lexical_cast)
#include <iostream>
#include <string>
#include <stdexcept>
int infini_asker(){
while (true) {
std::cout << "...: ";
std::string tmp;
std::cin >> tmp;
int i;
try{
i=std::stoi(tmp);
}catch(std::invalid_argument){
continue;
}catch(std::out_of_range){
continue;
}
return i;
}
}
int main(){
int num=infini_asker();
std::cout << " got:" <<num << std::endl;
}
A modification of Example 1 looks to be the best form:
while(true) {
cout << "...: ";
cin >> i;
/*... other stuff ...*/
// Do your input validation here:
// Note that it's much better to whitelist what is
// acceptable input as opposed to checking all of the
// possible cases of invalid input
if (...) { // where .. is the condition for valid input
break
}
}
do-while loops should be reserved for special cases where you want to get the point across that the nested logic should be executed at least once. Anything you can do with do-while, you can do with while(...)
for(;;) is less familiar syntax for a lot of programmers (I didn't know what it meant a year ago), whereas while(true) is much more obvious.
They all work. Like Shmiddty says a for(;;) is not a good programming habit. I would do it like example 2, but I am not a professional programmer.
void GasPump::dispense()
{
bool cont = true;
char stop;
do{
cout << "Press any key, or enter to dispense.\n"
<< "Or press 0 to stop: \n";
cin.get(stop);
gasDispensed = gasDispensed + gasDispensedPerCycle;
charges = costPerGallon*gasDispensed;
displayGasNCharges();
if(stop == 0)
cont = false;
} while(cont);
}
Doing an assignment, this is my first program to write with objects so bear with me.
I just can't get the output of this code to turn out right. I need a way to get out
of the loop, and what I'm using just isn't working. Any suggestions, hints or tips?
Try comparing stop to the zero char.
stop == '0'
Also you can simplify your code by doing this.
void GasPump::dispense()
{
char stop;
do {
cout << "Press any key, or enter to dispense.\n"
<< "Or press 0 to stop: \n";
cin.get(stop);
gasDispensed = gasDispensed + gasDispensedPerCycle;
charges = costPerGallon*gasDispensed;
displayGasNCharges();
} while (stop != '0');
}
In this scenario, you pump gas one extra time after the user hits '0'. Assuming that this is not desired, you have what is known as an "off-by-one error." You can fix this (and eliminate the temporary variable) by rearranging your function as follows:
void GasPump::dispense()
{
while (true) {
cout << "Press any key, or enter to dispense.\n"
<< "Or press 0 to stop: \n";
if (cin.get() == '0')
break;
gasDispensed = gasDispensed + gasDispensedPerCycle;
charges = costPerGallon*gasDispensed;
displayGasNCharges();
}
}
To avoid using a break statement, you can use the following construction:
bool GasPump::shouldDispenseGas()
{
cout << "Press any key, or enter to dispense.\n"
<< "Or press 0 to stop: \n";
return (cin.get() != '0');
}
void GasPump::dispense()
{
while (shouldDispenseGas()) {
gasDispensed = gasDispensed + gasDispensedPerCycle;
charges = costPerGallon*gasDispensed;
displayGasNCharges();
}
}
EDIT (2011 September 27):
#TonyK Just because a language provides a feature doesn't mean that one should use it. The goto statement is a classic example of this.
Granted, with such a simple loop, there's really no difference between using a function and the break. Both are clear. However, when extra features get added a month (or years) later, along with extra conditions for breaking out of the loop, it's very easy to find multiply-nested if statements with complex logic inside a loop that's so large, you have a hard time finding its beginning, much less the exit points. One of the ways to fight this type of code bloat is to write short, simple, and focused functions that are well-named. If you do this, the code documents itself. Compare
while (true)
versus
while (shouldDispenseGas())
Similarly, compare this to the STL for_each algorithm. Sure, std::for_each(v.begin(), v.end(), &foo); is a little shorter than for (int i = 0; i < v.size(); ++i) { ...body of foo()... }. But the real advantage is that it's easier to see what the intent is. In the for_each you immediately see that you will be doing something once, and only once, to each element. In the for loop, you have no idea. The loop counter i may be changed in the loop. A break may be hidden inside as well. By shirking this break statement and embedding the logic in shouldDispenseGas, you immediately understand the conditions under which the loop will continue, and end.