The trouble with input will always be the same. Not just for this program, but for every program you ever write in the future... So, it is worth understanding exactly what is going on.
Whenever your user presses keys on the keyboard it goes into the keyboard input buffer. Even though it isn’t stored the same way behind the scenes, you can think of it just like a text file.
So if I press:
Shift+H E L L O Space W O R L D Shift+1 Enter
then that goes into an input stream, the same as the file:
The actual stream contains the characters:
┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬
... │ H │ e │ l │ l │ o │ │ w │ o │ r │ l │ d │ ! │\n │ ...
┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴
↑
next character to read
Notice how we are looking at the stream: no beginning and no end.
When you ask for a space-delimited word (with
std::cin >> a_string
), the stream will skip any leading whitespace and then read all characters up until it finds a whitespace character.
┬───┬───┬───┬───┬───┬───┬───┬───┬
... │ │ w │ o │ r │ l │ d │ ! │\n │ ...
┴───┴───┴───┴───┴───┴───┴───┴───┴
↑
next character to read
Extracted from stream and
stored in your string:
"Hello"
Notice how the
next unread character is a space. If you again ask for a space-delimited string, C++ will skip the leading whitespace and again read everything until you get to whitespace:
┬───┬
... │\n │ ...
┴───┴
↑
next character to read
Extracted from stream and stored in your string:
"world!"
Notice how that newline (from when the user pressed
Enter) is still unread? This is typical of all
formatted input, stuff that looks like
std::cin >> something
.
However, if we use an
unformatted input it reads everything, up to and
including the newline:
┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬
... │ H │ e │ l │ l │ o │ │ w │ o │ r │ l │ d │ ! │\n │ ...
┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴
↑
next character to read
then
std::getline( std::cin, a_string )
, we get:
┬
... │ ...
┴
↑
next character to read
Everything is extracted, including the newline, and everything
except the newline is stored in the string:
"Hello world!"
.
This is why, after reading a number or anything using a formatted-input, you must then get rid of everything up to the next newline.
For example, if you ask for a number, and the input stream contains:
┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬
... │ 4 │ 2 │ o │ z │\n │ 1 │ 9 │ y │ r │ s │ ...
┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴
↑
next character to read
after
std::cin >> an_integer
, the stream will contain:
┬───┬───┬───┬───┬───┬───┬───┬───┬
... │ o │ z │\n │ 1 │ 9 │ y │ r │ s │ ...
┴───┴───┴───┴───┴───┴───┴───┴───┴
↑
next character to read
This is extra garbage left in the stream that needs to be removed. That is the reason for
std::cin.ignore( std::numeric_limits <std::streamsize> ::max(), '\n' );
, which simply reads and discards everything up to and including the next newline:
┬───┬───┬───┬───┬───┬
... │ 1 │ 9 │ y │ r │ s │ ...
┴───┴───┴───┴───┴───┴
↑
next character to read
Now the input stream is (again) in the proper state to read the next input.
Keeping track of this is part of your job as the programmer. It helps to keep in mind one simple principle:
The user will always press Enter after every input.
If you ask for a number, the user will type the number and press Enter.
If you ask for two numbers, the user will type two numbers and press Enter.
Whatever you ask for, the user will type it and press Enter.
A similar principle applies for text files. C++ handles everything with the same interface.
Hope this helps.