User input ends after inputting float - c++

I am trying to get a C++ program to output user inputs into an empty file. However, when after inputting a float, the program ends the current session of input by calling up the next session. Below is the code of the function for the user inputs.
vector<Item> insertProducts()
{
vector<Item> products;
string name;
string code;
float price;
string unit;
bool repeat = true;
while(repeat) // program will keep asking for another round of input after one session ends
{
cout << "Enter product description: ";
getline(cin, name);
if(name.compare("#") != 0) // program stop asking for input if # is entered
{
cout << "Enter product code: ";
getline(cin, code);
cout << "Enter product unit price: ";
cin >> price;
cout << "Enter product unit phrase: ";
getline(cin, unit);
cout << "" << endl;
Item newProduct = Item(code, name, price, unit);
products.push_back(newProduct);
}
else
{
repeat = false;
printCatalog(products);
}
}
return products;
}
Below is the result after inputting a float for price whereby the program skipped input of unit phrase and go right into another round of input.
Enter product description: Potato Chips
Enter product code: P3487
Enter product unit price: 1.9
Enter product unit phrase: Enter product description:
May I know what causes this problem and how can I solve it?

Your problem is that after cin >> price;, the newline character which the user used to terminate the input of the price is still in the input buffer—it's the next character to be read. The following std::getline then reads it and returns an empty line.
The most robust way of clearing such a trailing newline is to tell the stream to ignore everything up to and including the next newline:
cin >> price;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Use
cin.ignore();
before calling the getline() function
Alternatively, you can try using
cin.clear();
cin.sync();
at the beginning of your code
This will flush the input buffer.

Related

validate string input with while loop

I wanted to validate a string that will be inputted by the user which follows two conditions. The condition would be whether the string is empty or the string has a space char. My current problem is that I can validate the string but it would require me to press enter once more time to reiterate my question "2. Enter Product Name: ".
while (true) {
cout << "2. Enter Product Name: ";
if(getline(cin, newNode->product_name)) {
if ((newNode->product_name).empty() || (newNode->product_name) == " ") {
cout << "Please enter a valid product name!\n";
cin.clear();
cin.ignore(numeric_limits<std::streamsize>::max(), '\n');
}
else {
break;
}
}
}
Being inside the if statement if(getline(cin, newNode->product_name)) { means that the reading of a line succeeded. Therefore, you don't need the lines
cin.clear();
cin.ignore(numeric_limits<std::streamsize>::max(), '\n');
They will request an extra line to ignore, so remove that lines.

Catch cin exception

I want to ask the user for input, which I get with cin like this
void AskForGroundstate() {
cout << "Please enter an groundstate potential value in Volt:" << endl;
if (!(cin >> _VGroundstate)) {
cin.clear();
cin.ignore();
cout << "Groundstate potential not valid." << endl;
AskForGroundstate();
}
}
_VGroundstate is a double, so if the user enters an String with not numbers, it should ask him again for a better input. But the problem is, that when the input is for example "AA", than the program executes AskForGroundstate two times, with "AAA" three times etc. Did I use the clear wrong?
The problem is that cin.ignore() drops one character; you want to drop all characters to end of line:
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
This ensures that all invalid input is dropped before end-users are prompted for input again.

c++ loop runs forever without waiting for input

I am trying to write code that will loop and input user input to a class and print out a chart. This is my main method:
int main()
{
Company productMatrix;
int inputNumber = 0;
cout << "enter the salesman id or -1 to quit." << endl;
cin >> inputNumber;
while(inputNumber != -1)
{
int salesman = inputNumber;
cout << "enter the product id." << endl;
cin >> inputNumber;
int product = inputNumber;
cout << "enter the amount sold." << endl;
cin >> inputNumber;
double dollarValue = inputNumber;
productMatrix.inputSales(salesman, product, dollarValue);
cout << "enter the salesman id or -1 to quit." << endl;
cin >> inputNumber;
}
productMatrix.printChart();
cout << "Goodbye!";
return 0;
}
when I run the program, it will let me input one set of data and then loop forever without waiting for me to stop. This is what it looks like:
enter the salesman id or -1 to quit.
3
enter the product id.
2
enter the amount sold.
55.99
enter the salesman id or -1 to quit.
enter the product id.
enter the amount sold.
enter the salesman id or -1 to quit.
enter the product id.
enter the amount sold.
// etc...
I'm guessing there is something wrong with my loop. How can I fox this?
The problem is with following line.
double dollarValue = inputNumber;
inputNumber is a integer type and dollar value is a float. So there is a type mismatch. You can create another variable like dollarInput and store the dollar value there
You're writing a double 55.99 to an integer, so cin takes 55 and it has '.' in the buffer which is always !=-1 but never gets read into as integer.
inputNumber is an int. But you entered a value (55.99) that can not be interpreted as an int. This put cin into an error state. Until the error is cleared, all future operations with cin fail. So it doesn't wait for your input, and the variables retain their values, and you can never get that -1 that the loop needs to terminate.
To check for an error, just use a plain old if statement:
if (cin) {
// cin is okay
}
else {
// cin is not okay
}
You can also be a little more concise and put your input operation directly in an if statment:
if (cin >> inputNumber) {
To clear the error:
cin.clear();
You will also probably need to clear the input stream, otherwise the erroneous input will remain in the input buffer, and cin will just try to read it again:
cin.ignore(); // discard one character from the input buffer
// or
cin.ignore(N); // discard N characters from the input buffer
Anyway, that's the cause of the infinite loop. But if you had just input directly into a double, instead of an int, you wouldn't have seen this issue. Isn't that what you want anyway?
To add to prajmus's answer, you can see the additional 'junk' in the input stream by adding the following 'cin' read:
...
double dollarValue = inputNumber;
productMatrix.inputSales(salesman, product, dollarValue);
cout << "enter the salesman id or -1 to quit." << endl;
double myDbl;
cin >> myDbl;
cout << "read the following double:" << myDbl << endl;
...
The added "cin >> myDbl" will read the '.99' from the input stream and the added cout will yield:
0.99

Loop fails during first attempt

I am completing a lab assignment where the user is prompted for the type if fish they wish to order and to enter the price per pound. The user needs to be prompted for the type of fish and the price two times before the report prints.
The problem is that the program ends before the first instance of the loop has completed. (The way the code is written the titles on the report will print twice, but that was in the instructions.)
The code is below and any assistance is greatly appreciated.
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
float price;
string fishType;
int counter = 0;
// Change the console's background color.
system ("color F0");
while (counter < 3){
// Collect input from the user.
cout << "Enter the type of seafood: ";
cin >> fishType; // <------ FAILS AT THIS POINT. I GET THE PROMPT AND AT THE "ENTER" IT DISPLAYS THE REPORT
cout << "Enter the price per pound using dollars and cents: ";
cin >> price;
counter++;
}
// Display the report.
cout << " SEAFOOD REPORT\n\n";
cout << "TYPE OF PRICE PER" << endl;
cout << "SEAFOOD POUND" << endl;
cout << "-------------------------------" << endl;
cout << fixed << setprecision(2) << showpoint<< left << setw(25)
<< fishType << "$" << setw(5) << right << price << endl;
cout << "\n\n";
system ("pause");
return 0;
}
The new line character will not have been consumed by the read, using std::istream::operator>>(float), of the price:
cin >> price; // this will not consume the new line character.
The presence of the new line character during the next read, using operator>>(std::istream, std::string)), into fishType:
cin >> fishType; // Reads a blank line, effectively.
and then the user input that was intended to be the next fishType will be read (and fail to be) by the price as it will not be a valid float value.
To correct, ignore() until the next new line character after the read of the price. Something like:
cin.ignore(1024, '\n');
// or: cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Always check the status of input operation to determine if they were successful or not. This is easily achieved:
if (cin >> price)
{
// success.
}
If the fishType can contain spaces then using operator>>(std::istream, std::string) is not appropriate as it will stop reading at the first whitespace. Use std::getline() instead:
if (std::getline(cin, fishType))
{
}
When the user enters input a new line character will be written to stdin, i.e cin:
cod\n
1.9\n
salmon\n
2.7\n
On first iteration of the loop:
cin >> fishType; // fishType == "cod" as operator>> std::string
// will read until first whitespace.
and cin now contains:
\n
1.9\n
salmon\n
2.7\n
then:
cin >> price; // This skips leading whitespace and price = 1.9
and cin now contains:
\n
salmon\n
2.7\n
then:
cin >> fishType; // Reads upto the first whitespace
// i.e reads nothin and cin is unchanged.
cin >> price; // skips the whitespace and fails because
// "salmon" is not a valid float.

C++ Noobie - Why does moving these lines break my application?

This is my first attempt at C++, following an example to calculate a tip through a console application. The full (working code) is shown below:
// Week1.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
// Declare variables
double totalBill = 0.0;
double liquour = 0.0;
double tipPercentage = 0.0;
double totalNoLiquour = 0.0;
double tip = 0.0;
string hadLiquour;
// Capture inputs
cout << "Did you drink any booze? (Yes or No)\t";
getline(cin, hadLiquour, '\n');
if(hadLiquour == "Yes") {
cout << "Please enter you booze bill\t";
cin >> liquour;
}
cout << "Please enter your total bill\t";
cin >> totalBill;
cout << "Enter the tip percentage (in decimal form)\t";
cin >> tipPercentage;
// Process inputs
totalNoLiquour = totalBill - liquour;
tip = totalNoLiquour * tipPercentage;
// Output
cout << "Tip: " << (char)156 << tip << endl;
system("pause");
return 0;
}
This works fine. However, I want to move:
cout << "Please enter your total bill\t";
cin >> totalBill;
to be the first line under:
// Capture inputs
But when I do the application breaks (it compiles, but just ignores the if statement and then prints both cout's at once.
Im scratching my head becuase I cant understand what's going on - but I'm assuming I'm being an idiot!
Thanks
Try this
// Capture inputs
cout << "Please enter your total bill\t";
cin >> totalBill;
cin.clear();
cin.sync();
See c++ getline() isn't waiting for input from console when called multiple times
Or, better yet don't use getline at all:
cout << "Please enter your total bill\t";
cin >> totalBill;
cout << "Did you drink any booze? (Yes or No)\t";
cin >> hadLiquour;
totalBill is a number, i.e. the program "consumes" everything from your input that is a number. Let's say you entered:
42.2[RETURN]
The 42.2 gets copied into totalBill. The [RETURN] doesn't match, and remains in the input buffer.
Now, when you call getline(), the [RETURN] is still sitting there... I am sure you can figure out the rest from there.
Cin doesn't remove the newline character from the stream or do type-checking. So using cin>>var; and following it up with another cin >> stringtype; or getline(); will receive empty inputs. It's best practice to NOT MIX the different types of input methods from cin.
[for more informations see link]
you may change your code as below :
cout << "Please enter your total bill\t";
getline(cin, hadLiquour); // i used the hadLiquour string var as a temp var
// so don't be confused
stringstream myStream(hadLiquour);
myStream >> totalBill;