How can I break out of my do/while loop? - c++

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.

Related

Setting up a loop waiting for user input (C++)

I'm trying to get a simple tic-tac-toe program to function in the console as a way to make sure I understand loops and arrays.
It compiles, and runs as expected, with the exception that if a user inputs something that isn't a number the program races through the first if statement infinitely without a chance to add a new input. I really can't see how to fix this.
I think the issue is that chosenSquare is an integer as it needs to be compared to values, but cin can take anything in. Expected behaviour would be to check if the input is an integer between 0 and 8 (the 9 spaces on the board), and if not return a message and repeat, waiting for a new input.
Is there a simple fix for this? I'm trying to avoid specialist packages and namespaces for now while I grok the basics. I've looked at similar problems but don't follow them.
Thanks.
Code snippet:
// Input loop
bool valid = false;
while (valid != true)
{
int chosenSquare = 0;
cout << "Player " << currentPlayer << ", enter a number between 1 and 9:" << endl;
cin >> chosenSquare;
chosenSquare--; // For array indexing
if ((chosenSquare < 0) || (chosenSquare > 8)) // <--- PROBLEM IS THIS LOOP
{
cout << "Invalid input. Try again." << endl;
continue;
}
else if ((board[chosenSquare] == currentPlayer) || (board[chosenSquare] == lastPlayer))
{
cout << "Square not availible. Try again." << endl;
continue;
}
else
{
board[chosenSquare] = currentPlayer;
valid = true;
break;
}
}
There are a couple of things culminating causing this.
The first is that when an alpha character is put into the console, the error bit is set, and 0 is written to the variable you're writing to:
The behavior you want to observe changed in 2011. Until then:
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
But since C++11:
If extraction fails, zero is written to value and failbit is set. [...]
(From cppr.)
That means chosenSquare is 0 after the read, so chosenSquare-- makes it -1. -1, as you know, is less than 0, so the first if-statement is true.
As to why it stays this way infinitely, you need to clear the fail-bit.
So I changed the first loop after a bit of reading and experiementation:
if (cin.fail()) // <--- PROBLEM IS THIS LOOP
{
cout << "Invalid input. Try again." << endl;
cin.clear();
cin.ignore();
continue;
}
This works, but I can't figure out what it's actually doing.
Could anyone elaborate?

skip the whole loop without running the while

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.

C++ special-value-type loop has to exit when a negative value is entered without using break statement

I just completed a program that has to quit when a negative value is entered as input. Everything is working good except for only one issue, it quits the program after the second time a negative value is entered. After some research I noticed the use of break, however the samples I have to guide the assignment use only if and else statement.
#include <iostream>
using namespace std;
int main()
// insert code here...
// create a variable named "pounds" that can be used to store an integer.
// wait for the user to type in a value and put that value into the variable ounces
{
int poundsTotal;
int ouncesTotal;
while (poundsTotal >= 0)
{
cout << "Enter pounds or a negative number to quit: ";
cin >> poundsTotal;
ouncesTotal = poundsTotal * 16;
cout << poundsTotal << " pouds is " << ouncesTotal << " ounces." <<endl;
cout << " Enter pounds or a negative number to quit ";
cin >> poundsTotal;
poundsTotal++;
}
if (poundsTotal == 0){
cout <<"you enter a zero value" <<"Try onemore time";
}
else {
cout << "you chose to quit the program" <<poundsTotal;
}
}
The condition of a while loop is evaluated after the body has been executed. Then it is determined whether the body will be run again. Change your code and add an if statement inside the loop.
if(poundsTotal < 0) break;
And yes, a break statement is useful in a loop. Otherwise you can't stop the loop before your test condition is evaluated to false.
In your case, I find using a break would be a simple option.
When the program first reaches while (poundsTotal >= 0), poundsTotal has no defined value. This puts you at the mercy of the gods as to whether the program will work as expected or not, and Gods are notoriously unreliable. For more information, look up the term Undefined Behaviour.
The solution to this is ask the user for poundsTotal before the loop and once more at the end of the loop.
If you want to get really posh and do this without repeating code (and stay DRY) , make a function that gets poundsTotal from the user and call this function in the while loop's condition. For example,
while ((poundsTotal = getPoundsTotal()) >= 0)
{
...
}

while loop, really don't understand

hi im trying to do a while loop, im new to programming and reading online i cant really get my head around it, i have used flag to show that the inputted name matches the name in the data file, i want to do this so that after i know it doesnt match it loops it the whole thing again, i have no clue how to implement this,
{
clrscr();
cout << "This Is The Option To Delete A Record\n";
char yesno;
char search;
char name[21];
int flag = 0;
cout << "Enter Employee Name : ";
Input(name,20);
for (int r=0;r<row;r++)
{
if( strnicmp(name, emp[r].first_name, strlen(name) ) == 0 )
{
flag = 1;
clrscr();
cout << "Employee Number - " << emp[r].employee_number << endl;
cout << "Name - " << emp[r].first_name << " " << emp[r].surname << endl;
cout << "Department Number - " << emp[r].department_number << endl;
cout << "Week Ending Date - " << emp[r].weekend << endl;
cout << "Delete This Record (Y/N)? : ";
Input(yesno);
yesno = tolower(yesno);
if ( yesno == 'y' )
{
emp[r].deleted = true;
cout << "Record Has Been Deleted";
}
else if ( yesno == 'n')
{
cout << "Record Hasn't Been Deleted";
}
}
}
if (flag == 0)
{
cout << "There Are No Matching Records" << endl;
}
pressKey();
}
It's pretty simple, so have a bunch of code you want to keep executing it while a flag is zero, so that's just
int flag = 0;
while (flag == 0)
{
// whole bunch of code
}
That's it, just replace 'whole bunch of code' with the code you've written above.
Implementing this in a while loop would look like this:
bool flag=false;
while(!flag){
...
if(<find a match>) flag=true;
}
Assuming you understand the for loop, I think you can understand the while loop quite easily based on the comparison of for and while.
See, you used a for loop:
for (int r=0;r<row;r++){
// do stuff
}
There are 3 key points here.
int r=0 This is your initial condition.
r<row This is your condition which keeps the loop running.
r++ This is what happens at the end of each iteration of loop.
To rephrase the statements above:
Considering r equals zero initially, while r is less than row, increment r.
Now we can easily see how while loop is striking us:) To implement this, consider the following while loop example:
int r=0; //(1)
while(r<row){ //(2)
//do stuff
r++; //(3)
}
See, now the 2 loops do practically the same thing.
If you want to do operations based on a flag, you can also prefer an infinite loop:
while(1==1){
if(some condition)
break;
}
as well as an infinite for loop:
for(;;){
if(if some condition)
break;
}
Again, 2 loops are practically the same.
so basically, you have a file with some data. And also, you accept some data from the user.
And then you perform a comparison between the appropriate fields of the two sets.
Why would you want to do it all over again once the entire comparison (file process) is done?
if you simply want to run an infinite loop, you can do this:
while(true)
{
//your code
}
you can do same with a for loop also. infact for loop and while loop both are same except for the syntax. i.e. an infinite for loop.
for (int r=0;r<row;r++)
{
if(r==row-1)
{
r=0;
}
}
I guess what you want to do is to, once one set of user input doesn't match the file content, you want to take another set and match it again and so on.
so you don't need an infinite or always executing loop for this.
Just make your comparison module a separate function which should accept the set of user inputs. All you do is accept user inputs and show the result. And give the user an option to re-enter inputs.
Below is simple algo for what you want.
int main()
{
char a='a';
while(a != '~')
{
TakeUserInput();
if(PerformComparison())
{
cout << "Success";
break;
}
}
}
inside TakeUserInput() you do all those cin << to set a global array or set of global variable. also, you cin << a, to terminate program at your will.
and inside PerformComparison(), you do what you have posted here in your question.

Making an if condition return if its true or while return if its true

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
}