简体   繁体   中英

Problem of using cin twice

Here is the code:

string str;
cin>>str;
cout<<"first input:"<<str<<endl;
getline(cin, str);
cout<<"line input:"<<str<<endl;

The result is that getline never pauses for user input, therefore the second output is always empty.

After spending some time on it, I realized after the first call "cin>>str", it seems '\\n' is still stored in cin (using cin.peek() to check), which ends getline immediately. The solution will be adding one more line between the first usage and the second one: cin.ignore(numeric_limits::max(), '\\n');

However, I still don't understand, why is '\\n' left there after the first call? What does istream& operator>> really do?

The \\n is left in the input stream as per the way operator>> is defined for std::string . The std::string is filled with characters from the input stream until a whitespace character is found (in this case \\n ), at which point the filling stops and the whitespace is now the next character in the input stream.

You can also remove the \\n by calling cin.get() immediately after cin>>str . There are many, many different ways of skinning this particular I/O cat, however. (Perhaps a good question in and of itself?)

As others have said, th problem is that the newline is left from the first extraction. One solution I do is to discard all the left characters in the stream:

std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );

I generally recommend only doing line-oriented input from std::cin. So, your code could look something like this:

string str;
int val;
// Read an entire line and parse an integer from it
{
    string line;
    getline(cin, line);
    istringstream iss(line);
    iss >> val;
}
cout<<"first input:"<<val<<endl;
getline(cin, str);
cout<<"line input:"<<str<<endl;

Be sure to add error checking too.

The getline-only approach avoids having to think about line buffering of the input, of clearing the input, etc. If you directly read something with >>, the input does not terminate if the user hits enter instead of inputting what is required, but instead continues until a token is input (this behavior is usually not wanted).

By default, the stream insertion operator reads until it sees whitespace. Your first call isn't returning until it sees a space, tab, newline, etc. Then the next character needs to be consumed so that you can get to the next one.

好的写作解释了为什么遇到这个问题的一些原因 ,主要是由于输入类型的行为以及你正在混合它们

Also was searching for most suitable solution. Implementation of this operator could produce problems. And not always is acceptable to read entire line, or not mix different types in one input line.

To solve problem, when you want to read some data from cin , and don't know if whitespaces was correctly extracted after last input operation, you can do like this:

std::string str;
std::cin >> std::ws >> str;

But you can't use this to clear trailing newline symbol after last input operation from cin to do not affect new input, because std::ws will consume all whitespaces and will not return control until first non-ws character or EOF will be found, so pressing enter will not finish input process. In this case should be used

 std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );

which is more flexible.

PS If got errors with max() function such as "identifier expected", it could be caused by max macros defined in some header (for example, by Microsoft); this could be fixed by using

 #undef max

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM