Loop in C++ not working again - c++

So I've been troubleshooting this program and I've already asked questions about it before. I've taken other people's advice seriously and have applied it to my program, but it's still not working. This is the modified (albeit shortened) code:
#include <iostream>
#include <string>
double balance, withdraw, deposit;
std::string choice;
void withdrawmon()
{
balance -= withdraw;
}
void depositmon()
{
balance += deposit;
}
int main()
{
std::cout << "Welcome to the Bank Program." << std::endl;
std::cout << "Enter a starting balance: ";
std::cin >> balance;
std::cin.clear();
do
{
std::cout << "Withdraw, deposit, or quit: ";
std::getline (std::cin, choice);
if(choice == "withdraw")
{
std::cout << "Enter amount to withdraw: ";
std::cin >> withdraw;
withdrawmon();
std::cout << "Your current balance is $" << balance << std::endl;
}
else if(choice == "deposit")
{
std::cout << "Enter amount to deposit: ";
std::cin >> deposit;
depositmon();
std::cout << "Your current balance is $" << balance << std::endl;
}
}
while(choice != "quit");
std::cout << "Thanks for using the Bank Program. Your final balance was $" << balance << std::endl;
return 0;
}
There wouldn't be a problem, and the code runs, but the output is like this:
https://www.dropbox.com/s/aocn6asjr4ofcws/Broken%20Output.PNG
As you can see the "Withdraw, deposit, or quit:" line prints itself twice whenever the loop restarts. Anyone know why? Any help is appreciated. I'm a new programmer as far as C++ goes, so any help is appreciated.

cin.clear() clears the error flag and leaves the remaining contents of the line that follow the input balance in the buffer. You need can call cin.ignore() to handle this properly.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

You're mixing stream extraction operators with getline. In your example, std::cin>>withdraw got the string "50" when the user entered "50\n". The next getline just gets the "\n", which is why you get the prompt twice ("\n" != "quit").
You can solve this a few ways: Either use getline for everything and get what you need out of each line, call getline after your cin>> to make the next read operation begin at the next line, or, as Captain Oblivious suggested, use cin.ignore.

Related

program ignores everything after cin.get() and skips back to the menu

I'm stuck with this problem and I've tried everything I can think of. My program is a music database with a menu for selecting options.
I have a function for reading in data to add a new song to the database. My cin.get() statements seem to work, and it's echoing back the right information. But as soon as I get to the last cin.get(), it just skips straight back to the menu. I put in some dummy cout statements after this chunk of code and they never execute.
Here the function I'm having trouble with. I can post the rest of the program if necessary. I would really appreciate help with this. I'm betting this is something really simple, I'm just too much of a beginner to see what the problem is.
Thanks in advance for any help!
void inputNew(songType songs[], int &numSongs)
{
char songName[100];
char artist[100];
int min;
int sec;
char album[100];
clearScreen();
cout << "Enter the name of the song: ";
cin.get(songName, 100, '\n');
cin.ignore(100, '\n');
cout << "You entered: " << songName << endl;
cout << "Enter the name of the artist: ";
cin.get(artist, 100, '\n');
cin.ignore(100, '\n');
cout << "You entered " << artist << endl;
cout << "Enter the minutes: ";
cin >> min;
cout << "You entered " << min << "minutes" << endl;
cout << "Enter the seconds: ";
cin >> sec;
cin.ignore(100, '\n');
cout << "You entered " << sec << "seconds" << endl;
cout << "Enter the album name: ";
cin.get(album, 100, '\n');
cin.ignore(100, '\n');
cout << "testing" << endl;
In the repl you posted in the comments main has a while loop.
while (answer != 'q')
{
displayMenu(songs, answer, numSongs);
processRequest(songs, answer, numSongs); // Internally calls inputNew
}
displayMenu clears the screen and writes the menu. If you don't break in some way the execution, you will not be able to see the text that processRequest wrote. You need to add an std::cin.get() after all your outputs (like at the end of processRequest). If you want you can add a message like Press enter to continue... right before std::cin.get().

c++ While loops prints the couts twice

In my code, the while loop prints the cout twice when it should print it once, as well as the function's couts. I don't understand why it's doing this - it is supposed to display
What would you like to do?
Deposit
Withdraw
Cancel
But, it displays that twice.
while (yesNo == 'Y') {
cout << "What would you like to do?"
<< endl
<< endl;
menu();
getline(cin, bankChoice);
if (bankChoice == "Withdraw")
{
withdrawTotal = withdraw(bankAmount);
bankAmount = withdrawTotal;
cout << "You now have $"
<< bankAmount
<< " in your account."
<< endl;
cout << "Would you like to do anything else?"
<< endl
<< "Y/N: ";
cin >> yesNo;
}
if (bankChoice == "Deposit")
{
depositTotal = deposit(bankAmount);
bankAmount = depositTotal;
cout << "You now have $"
<< bankAmount
<< " in your account."
<< endl;
cout << "Would you like to do anything else?"
<< endl
<< "Y/N: ";
cin >> yesNo;
}
if (bankChoice == "Cancel") {
return 0;
}
}
That is the loop I am using. If additional code is needed I can post it as well, but this is the part that is causing the issue. I've tried the code without it and it works fine, but I'd like to get the code to loop until the user enters 'N'.
You are using both std::getline and operator>> to read from std::cin. operator>> does not consume the trailing newline, so the next call to std::getline() will immediately read the following newline and interpret it as an empty line of text that was entered. This will run through the loop, and go back up to the top, for the second prompt.
Never use operator>> with std::cin when you intend to read a single line of text.
The following short example demonstrates this point:
#include <iostream>
#include <string>
int main()
{
char c;
std::string l;
std::cin >> c;
std::cout << "A line of text please: ";
std::getline(std::cin, l);
}
Run it, enter "Y", and try to figure it out, yourself, why the program terminates immediately.
Once again: don't use operator>> to read lines of text from std::cin. It is a recipe for grief, and bugs.
In addition to Sam's answer, I'd like to recommend that you extract common functionality outside your two if statements:
std::string yesNo;
while (yesNo.compare("Y") == 0) {
cout << "What would you like to do?"
<< endl
<< endl;
menu();
getline(cin, bankChoice);
if (bankChoice == "Cancel")
return 0;
if (bankChoice == "Withdraw") {
withdrawTotal = withdraw(bankAmount);
bankAmount = withdrawTotal;
}
if (bankChoice == "Deposit") {
depositTotal = deposit(bankAmount);
bankAmount = depositTotal;
}
cout << "You now have $"
<< bankAmount
<< " in your account."
<< endl;
cout << "Would you like to do anything else?"
<< endl
<< "Y/N: ";
std::getline(std::cin, yesNo);
}

reading and printing inputs and C-string in C++

I have a simple program to read and echoed the user's input and calculate the total amount. I'm having trouble with arrays. I want to know how to use an array to read and print each product name and the cost and the find grand total upon checkout. Should I also use functions?
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
const int MAX_CHAR = 100;
void pause();
int main()
{
char productName[MAX_CHAR];
double price;
char reply;
double total = 0;
cout << fixed << showpoint << setprecision(2);
cout << "Welcome to your shopping calculator!" << endl;
do {
cout << "Enter the product name: ";
cin.get(productName, MAX_CHAR, '\n');
cin.ignore(100, '\n');
cout << "Enter the amount: $";
cin >> price;
while (!cin) {
cin.clear();
cin.ignore(100, '\n');
cout << "Invalid amount. Please enter the amount: $";
cin >> price;
}
cin.ignore(100, '\n');
cout << "The product name is" << " " << productName << " "
<< " and it costs" << " " << "$" << price << endl;
total += price;
cout << "The total amount is " << " " << total << endl; //program needs to keep a running total
cout << "Would you like to continue shopping? (y/n): ";
cin >> reply;
cin.ignore(100, '\n');
} while ( reply == 'Y' || reply == 'y'); //the program will continue until the user wants to checkout
pause();
return 0;
}
void pause()
{
char ch;
cout << "Press q followed by Enter key to continue....." << endl;
cin >> ch;
}
Thanks for the help!
You need to map the product name to the cost using std::map so that you can print the respective pairs afterwards. As for the grand total, that's stored in the variable total so printing it is trivial.
To do this, you will need to include the <map> header, as the Standard Library class std::map is defined there. Moreover, I've also included some changes to your code that should be considered. In particular, using std::string and using std::numeric_limits<...>::max() to return the constant.
#include <iostream>
#include <string>
#include <map>
int main()
{
std::string productName;
double price;
char reply;
double total = 0;
std::map<std::string, double> productToPrice;
std::cout << std::fixed << std::showpoint << std::setprecision(2);
std::cout << "Welcome to your shopping calculator!" << std::endl;
while ((std::cin >> reply) && (reply == 'y' || reply == 'Y'))
{
cout << "Enter the product name: ";
std::cin >> productName;
cout << "Enter the amount: $";
while (!(cin >> price))
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Invalid amount. Please enter the amount: $";
}
total += price;
productToPrice.insert(std::make_pair(productName, price));
cout << "Would you like to continue shopping? (y/n): ";
}
...
}
Note the changes I made. Please use them.
To print you simply do:
typedef std::map<std::string, double>::const_iterator iter_type;
for (iter_type beg(productToPrice.begin()),
end(productToPrice.end()); beg != end; ++beg)
{
std::cout << beg.first << " -- " << beg.second << std::endl;
}
std::cout << "\nThe total price is: " << total;
You are definitely on the right track. I think you are mixing I/O conventions in C and C++ which is causing a lot of your issues. It would be very helpful if you could elaborate on what exactly your issues are.
Carpetfizz is correct in that since you don't know the number of items at compile time, you will need to use a dynamic array with std::vector. You can learn about vectors here.
In addition, C++ has a very useful string data type that you can include with #include <string>. Using this, as well as a junk string such as string junk;, you can avoid using cin.ignore(...) and get cleaner I/O by using getline(cin, junk).
I strongly recommend doing this because creating a vector of C-strings or C-style strings is a pain, because C-style strings are actually arrays of characters, so you'd have to use std::vector<std::vector<char> > products.

C++ if statement in function

So I am trying to write a basic program that will keep track of a balance, and you can make a withdraw, make a deposit, and quit the program altogether. This is the code.
#include <iostream>
#include <string>
using namespace std;
double balance = 0, withdraw = 0, deposit = 0;
string choice;
class Bank
{
public:
void withdrawMoney()
{
if(balance - withdraw >= 0)
{
balance = balance - withdraw;
}
else
{
cout << "$5 penalty for attempting to withdraw more than you have.";
balance -= 5;
}
}
public:
void depositMoney()
{
balance = balance + deposit;
}
};
int main()
{
Bank bankObject;
cout << "Welcome to the Bank Program!" << endl;
while(true)
{
cout << "Would you like to make a withdrawal, a deposit, or quit the program: ";
cin >> choice;
if(choice.compare("withdrawal") == 0)
{
cout << "Please enter the amount to withdraw: ";
cin >> withdraw;
bankObject.withdrawMoney();
cout << "New balance is: $" << balance << endl;
}
else if(choice.compare("deposit") == 0)
{
cout << "Please enter the amount to deposit: ";
cin >> deposit;
bankObject.depositMoney();
cout << "New balance is: $" << balance << endl;
}
else if(choice.compare("quit") == 0)
{
break;
}
else
{
cout << "Invalid input." << endl;
}
cout << "Would you like to try again or quit: ";
cin >> choice;
if(choice.compare("quit") == 0)
{
break;
}
}
cout << "Thank you for using the Bank Program." << endl;
return 0;
}
I am new to C++, (I started today), but I have previous experience with Java. I am continually getting an error at the withdraw method, at the first if statement, saying that I have an invalid use of the member function. Any help would be appreciated. Also, not sure if it matters, but I am using the IDE Code::Blocks.
EDIT: First problem fixed, but now there is another, when I run the code, I can get through it once just fine, but when I try to go through a second time by typing try again, it gets stuck in a loop and answers the first question as "incorrect input". Help?
You use withdraw as both a global variable and a method name. Renaming one of them should fix this particular error.
Edit: When you type "try again", your program only reads "try" (because the default is to break up the input by whitespace), leaving "again" in the buffer for the next read from cin. You can verify that with a few debugging output statements.

Program not waiting for cin

int x=0;
string fullname = "";
float salary;
float payincrease;
float newsal;
float monthlysal;
float retroactive;
while(x<3){
cout << "\n What is your full name?";
cin >> fullname;
cout << "\n What is your current salary? \t";
cin >> salary;
cout << "\n What is your pay increase? \t";
cin >> payincrease;
newsal = (salary*payincrease)+salary;
monthlysal = newsal/12.00;
retroactive = (monthlysal*6)-(salary/2);
cout << "\n" << fullname << "'s SALARY INFORMATION";
cout << "\n New Salary \t Monthly Salary \t Retroactive Pay";
cout << "\n \t" << newsal << "\t" << monthlysal << "\t" << retroactive;
x++;
}
My loop doesn't seem to stop for every time cin is asked, and instead instantly executes the loop 3 times on its own. How do I get it to stop when input is asked?
If the input stream isn't empty when you call cin, then cin uses the data already in the buffer instead of waiting for more from the user. You're using the extraction operator, so when cin is sending values to your variables, it skips leading whitespace in the buffer and stops on the next whitespace.
Put a breakpoint on this line:
cout << "\n What is your current salary? \t";
Run the program, and enter Bob Smith. When you hit the break point, hover your cursor over your string fullname. You'll see it stores only "Bob" not "Bob Smith". "Bob Smith" got put into the buffer, but when you use cin with the extraction operator, it skips any leading whitespace, puts the next value it finds into your variable, then stops on the next whitespace. To demonstrate this, try running this:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1,str2;
cin >> str1;
cin >> str2;
cout << str1 << " " << str2 << "\n\n";
return 0;
}
If you type in "Bob Smith", it will take your input only one time, even though you call cin twice. However, you'll see that both "Bob" and "Smith" got captured in the strings str1 and str2.
Therefore, you can conclude that cin stops populating your string fullname when it gets to the space between Bob and Smith. On your next call to cin, the buffer still contains "Smith", so instead of taking more input from the user, it attempts to fill your variable salary with "Smith". Obviously this isn't want you want to do. You can call flush and ignore on cin to wipe out the buffer before every time you use cin, or instead you could fix your logic and use getline to take in the full name, including spaces.
To fix your problem, all you need to do is use getline instead of cin >>, so replace this line:
cin >> fullname;
with this:
getline(cin,fullname,'\n');
Secondly, you're using a while loop to execute a set of actions a specific number of times. That's typically something you'd use a for loop for.
As an aside, you could also write tiny input validation loops that can help you debug or otherwise avoid attempting to put invalid input into your variables (such as "Smith" into a float). Something like this could work:
for(;;)
{
if(cin >> salary)
break;
cin.clear();
cin.ignore(INT_MAX,'\n');
}
Note that cin returns a value, so you can use it in an if statement. If it gets valid input, it will return true. If not, it will return false. To make it more explicit, you could also just use a normal call to cin without the if statement, and then check if cin.good(), which amounts to basically the same net effect. If you're not using Visual Studio and get an error about INT_MAX, you might need to #include limits.h to resolve it.
That occurs if you input a char where an int is expected.
Use cin.clear(); and cin.ignore(numeric_limits<streamsize>::max(), '\n'); to limit an input to int's only.
Other than that, it won't skip if the correct data type is put in.
#include <string>
#include <iostream>
#include <limits>
using namespace std ;
int main(void)
{
int x=0;
string fullname = "";
float salary;
float payincrease;
float newsal;
float monthlysal;
float retroactive;
while(x<3)
{
cout << "\n What is your full name?";
cin >> fullname;
cin.ignore( 1000, '\n' );
cout << "\n What is your current salary? \t";
cin >> salary;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "\n What is your pay increase? \t";
cin >> payincrease;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
newsal = (salary*payincrease)+salary;
monthlysal = newsal/12.00;
retroactive = (monthlysal*6)-(salary/2);
cout << "\n" << fullname << "'s SALARY INFORMATION";
cout << "\n New Salary \t Monthly Salary \t Retroactive Pay";
cout << "\n \t" << newsal << "\t" << monthlysal << "\t" << retroactive;
x++;
}
cout<<" \nPress any key to continue\n";
cin.ignore();
cin.get();
return 0;
}
Check your variable types, I noticed mine accepting a digit instead of a character, had the same problem (not stopping, loop just kept going on).
> std::cin >> this->controls.button
> DETOX_NUMBER button; // (int)
Change to:
> char button;