I tried to run the following code but after one input, the rest of the input is initialized to zero and is displayed on the screen automatically. where did I go wrong?
#include<iostream>
#define N 50
using namespace std;
struct movies_t
{
char title[60];
int year;
}user[N];
void printmovie(movies_t);
int main()
{
for(int i = 0; i < N; i++)
{
cout << "Enter title: ";
cin.get(user[i].title, 60);
cout << "Enter year: ";
cin >> user[i].year;
}
cout << "\nYou have entered these movie: \n";
for(int i = 0; i < N; i++)
printmovie(user[i]);
return 0;
}
void printmovie(movies_t m)
{
cout << m.title;
cout << " (" << m.year << ")\n";
}
The problem is that when you press enter after inputting the year for the first movie, that enter (newline) is still in the input buffer, so when you next call cin.get(...) it will read that newline and think you entered an empty line.
You need to tell cin to ignore the rest of the line including the newline.
After execution of
cin >> user[i].year;
the newline character is still left in the input stream.
The next time you execute
cin.get(user[i].title, 60);
the first character encountered is the newline character. When that happens, failbit of cin is set. Here's some info from http://en.cppreference.com/w/cpp/io/basic_istream/get (emphasis mine):
4) Reads characters and stores them into the successive locations of the character array whose first element is pointed to by s. Characters are extracted and stored until any of the following occurs:
n-1 characters have been stored
end of file condition occurs in the input sequence (setstate(eofbit) is called)
the next available input character c equals delim, as determined by Traits::eq(c, delim). This character is not extracted (unlike basic_istream::getline())
If no characters were extracted, calls setstate(failbit). In any case, if count>0, a null character (CharT() is stored in the next successive location of the array.
After the failbit of cin is set, nothing is read from cin until the state is cleared by an explicit call to cin.clear().
Since you don't have any code to check the state of cin and clear the state when appropriate, nothing is read in the loop after the first iteration.
One way to fix the problem is add a line to ignore the contents of the stream after the year is read.
cin >> user[i].year;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Also, it is a good practice to always check the state of a stream after an IO operation to make sure that you don't overlook any errors.
for(int i = 0; i < N; i++)
{
cout << "Enter title: ";
cin.get(user[i].title, 60);
if ( !cin )
{
cout << "Error reading title.\n";
exit(1);
}
cout << "Enter year: ";
cin >> user[i].year;
if ( !cin )
{
cout << "Error reading name.\n";
exit(1);
}
// Ignore everything up to and including the newline character.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Related
This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Using getline() in C++
(7 answers)
Closed 4 years ago.
Can anyone explain why I am having trouble with the below C++ code?
#include <iostream>
using namespace std;
class stud
{
public:
string name,adrs;
long long unsigned int mob;
};
int main()
{
stud s[10];
unsigned int num;
cout << endl << "Enter the number of students(<10): ";
cin >> num;
cout << endl;
for(int i = 0; i < num; i++)
{
cout << endl << "Enter student " << i+1 << " name(put '.' at end and press enter): ";
getline(cin, s[i].name); // this line skips some data before even they are
//entered and there is no error while compiling
}
system("CLS");
for(int i = 0; i < num; i++)
{
cout << endl << " Student " << i+1 << " name is: ";
cout << s[i].name << endl;
}
return 0;
}
When I try to input a string value for an object in the array as above, using getline() without any delimiter (which uses a new line by default), I don't get correct output since some other data is automatically being skipped.
But, when I use getline() as follows instead of above, it works fine, but it needs a delimiter at the end:
getline(cin, s[i].name, '.');
Please help me find a solution. I think the Enter key is pressed several times at one key press, and that's why the getline() skips some data. I'm not sure about this, though.
before correcting you program one thing to know is that
Actually, a newline is always appended to your input when you select Enter or Return when submitting from a terminal.
cin>> doesn't remove new lines from the buffer when the user presses Enter.
This has little to do with the input you provided yourself but rather with the default behaviour std::getline() exhibits. When you provided your input for the name (std::cin >> num;), you not only submitted the following characters, but also an implicit newline was appended to the stream, getline() mistakes this for user input along with enter.
It is recommended to use cin.ignore() to get rid of those extra characters after using cin>>(whatever) if you are going to use getline(cin,any string) later.
Edit this part of your code:
stud s[10];
unsigned int num;
cout << endl << "Enter the number of students(<10): ";
cin >> num;
cout << endl;
cin.ignore();//just add this line in your program after getting num value through cin
//fflush(stdin);
//cin.sync();
//getchar();
for(int i = 0; i < num; i++)
{
cout<<endl<< "Enter student " << i+1 << " name(put '.' at end and press enter): ";
getline(cin,s[i].name);
}
system("CLS");
you can use and may be tempted to use fflush(stdin) also but it is not recommended as it has undefined behaviour, as
According to the standard, fflush can only be used with output buffers, and obviously stdin isn't one.
about cin.sync():
using “cin.sync()” after the “cin” statement discards all that is left in buffer. Though “cin.sync()” does not work in all implementations (According to C++11 and above standards).
you can also use getchar() to get the newline caused by Enter
I'm learning c++ and reading c++ primer plus, but I don't understand why this code need two "cin >> ch". I know the first cin will read character that was user input.but then I delete first "cin >> ch" and run code ,the program have no error.So the fist cin is necessary? why the second cin needn't user to input?
#include <iostream>
int main()
{
using namespace std;
char ch;
int count = 0;
cout << "Enter characters; enter # to quit:\n";
cin >> ch; //get a character
while (ch != '#')
{
cout << ch;
++count;
cin >> ch; // get the next character
}
cout << endl << count << " characters read\n";
return 0;
}
You can evaluate your input right inside condition of while loop.
#include <iostream>
int main()
{
char ch;
int count = 0;
std::cout << "Enter characters; enter # to quit:\n";
while (std::cin >> ch && ch != '#')
{
std::cout << "entered: " << ch << std::endl;
++count;
}
std::cout << std::endl << count << " characters read" << std::endl;
return 0;
}
When while condition is entered it will wait for you to enter anything first. Once input is received it will check if the input is not #. If input is not # the loop is entered, input printed out, counter increased, and back to waiting for another input. If # is entered, condition becomes false, and loop is aborted.
If you remove the first cin then count will never be incremented. The user can enter # character before entering the loop and the program can never enter it therefore.
The first cin>>ch is obviously used to take input from user but you
have again accepting data in while loop using the same variable name "ch" ,
So when you run the program it will not give u error but accept only first value that you have accept before the while loop not in while loop.
In while loop you can assign new value to variable "ch" but not accept the new value again.
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.
Is there a way to use cin.clear() or cin,ignore() for ONLY the previous line of input without clearing ALL previous input? For example in my code I prompt the user for input for each month, well if the input is less than 0 I would like the program to clear that negative input so that it does not get total into my calculation. Problem is it clears ALL previous input which still screws up the calculation. Thanks for any ideas in advance.
// prompt user for input, keep a total sum of data entered
for(int i = 0; i < 12; i++)
{
cout << "Enter total rainfall for " << year[i] << endl;
cin >> month[i];
total += month[i];
while(month[i] < 0)
{
cout << "Ony enter positive numeric values!" << endl;
cin.clear();
cin >> month[i];
}
}
You seem to be mixing up two distinct issues. ios_base::clear()
doesn't remove any input; it resets the error status of the stream.
istream::ignore( n, ch ), on the other hand, reads forward until n
characters have been extracted or a character ch is seen'
myInput.ignore( INT_MAX, '\n' ) should ignore everything up to (and
including) the next '\n'.
but your code has one thing that is very strange:
cin << month[i];
You can't output to std::cin.
You probably want something like this:
unsigned int month[12];
for(size_t i = 0; i < 12; i++)
{
cout << "Enter total rainfall for month " << i+1 << endl;
while (!(cin >> month[i]))
{
cout << "Invalid input, try again." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
// you probably want to repeat ignore() stuff here
// so in case user inputs something like 10x, the "x" that was left
// in the stream gets discarded
}
Note the array of unsigned integers. This way input like "-5" is automatically considered invalid so you don't need the less than 0 check. Clearing the entire stream shuouldn't worry you - if the input operation succeeds, the relevant part is already stored in your array.
I call a function from a function in C++ that has the line getline(cin,name) where name is a string. the first time through the loop, the program does not wait for input. It will on all other passes through the loop. Any ideas on why?
void getName (string& name)
{
int nameLen;
do{
cout << "Enter the last Name of the resident." << endl << endl
<< "There should not be any spaces and no more than 15"
<< " characters in the name." << endl;
getline(cin,name);
cout << endl;
nameLen = name.length();// set len to number of characters input
cout << "last" << name << endl;
}
while (nameLen < LastNameLength);
return;
}
Make sure there isn't left overs since the last time you read something from cin, like:
In an earlier point in your program:
int number;
cin >> number;
The input you give:
5
Later in the program:
getline(cin,name);
and getline will seem to not be called, but rather it collected the newline from the last time you took input because when you use cin >> it leaves new lines.
It may be because of the input stream. The getline function stops reading input after is receives the first newline char. If for example there are multiple newlines within the buffer of std::cin - the getline will return every time it encounters one.
Check the input you are expecting.
Do you have any:
cin << variableName;
lines of code? I ran into getline() skipping run-time errors when I was using:
cin << intvariable and subsequently getline(cin, variable).
This is because the cin stream object holds a buffer of input. When you enter the newline character I assume it is trunacated from the stream going to the variable asisgnment, yet is still contained within the cin object instance itself.
One workaround I used is cin.ignore(); after the cin << integer statement.
Another user mentioned parsing all input from getline into integers, floats - not root beer -, and strings. Good luck and check your code for the dual use of cin & getline().