C++ input streams have two different modes of input. When we use the
>> operator, we are doing formatted input; when we don't (for instance we do a
std::getline()
or a
std::cin.getline()
)we are doing unformatted input.
1 2
|
int i ; std::cin >> i ; // formatted input
std::string line ; std::getline( std::cin, line ) ; // unformatted input
|
The formatted input
operator >>
discards leading white space, and stops reading when it encounters a white space (or invalid input). Unformatted input on the other hand, does not discard leading whitespace.
If the contents of the input buffer was:
<space> <newline> 1 2 3 4 <space> <newline> a b c d <newline>
and we do
int i ; std::cin >> i ;
the formatted input operation discards leading white space:
<space> <newline>
, reads the next four characters to form an integer:
1 2 3 4 => i
and leaves
<space> <newline> a b c d <newline>
in the input buffer.
Now, if we do
std::string line ; std::getline( std::cin, line ) ;
the unformatted input does not discard leading whitespace - the
getline()
reads characters into the string till a
<newline>
is encountered, and then reads the
<newline>
and discards it without appending it to the string. After the
getline()
, the string contains a
<space>
and the input buffer has
a b c d <newline>
.
Now let us say, we want to read an int (formatted input) and a string (using unformatted input) from stdin. We write:
1 2 3 4
|
int number ;
std::string text ;
std::cin >> number ;
std::getline( std::cin, text ) ;
|
We run the program and enter
12345<newline>
on
stdin.
std::cin >> number ;
reads
12345 into
number and leaves the
<newline>
in the input buffer. The program continues with
std::getline( std::cin, text ) ;
The
getline()
sees that the input buffer is not empty, so it does not wait for any input to be entered. It returns immediately after reading an empty string, and extracting the
<newline>
in the buffer and throwing it away.
The best solution to the problem is not to mix formatted and unformatted input - they don't play well together. (How to do this to read numbers and lines of text might be a little beyond your depth right now).
The other option is to make the stream discard trailing white space left by the formatted input operation. This can be done by:
1 2 3 4 5
|
int number ;
std::string text ;
std::cin >> number ;
std::cin.ignore( 1024, '\n' ) ;
std::getline( std::cin, text ) ;
|
std::cin.ignore( 1024, '\n' ) ;
will extract and discard up to 1024 characters or until a '\n' is extracted and thrown away. The 1024 in the example is just a reasonably large enough value, because we don't expect that more than that many characters would need to be discarded.
A more robust, 'correct' version would be:
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ) ;
std::numeric_limits<std::streamsize>::max()
being the largest possible number of characters an input buffer can possibly hold at one time.