0
int main()
{
    string a, b;
    
    cin >> a;
    // cin.ignore(10000, '\n');
    getline(cin, b);        // in this case, it wouldn't ignore the \n, so it would just terminate without taking the input
    
    cout << a << endl;
    cout << b << endl;
}

My question is specifically on why '\n' is left in the input stream, and the rules regarding cin and getline(), regarding white spaces and delimiters.

  • @273K Thanks, I guess the OP can read the dup – john Dec 13 '22 at 07:05
  • @j But you were right. Whitespace is not considered a part of a string/word. – 273K Dec 13 '22 at 07:06
  • `cin >> a` and `getline(cin, b)` have very precise (and not very complicated) rules about what they do and do not read. You should familiarise yourself with them. – john Dec 13 '22 at 07:07
  • 1
    BTW these rules are about what is and is not read. 'The buffer' is not any part of these rules, despite what you might have heard. Just concentrate on what is or is not read. When you are doing console input it can be the case that characters can be typed but not yet read, and that is sometimes called the buffer, but it really is not relevant. – john Dec 13 '22 at 07:13
  • 1
    `ignore()` of course is also part of these rules, but again nothing to do with any buffer. – john Dec 13 '22 at 07:15
  • @John Where can I find these rules? My question has still not been answered. It was on why '\n' is left in the stream. I knew how all of this worked that was explained in the other thread. –  Dec 14 '22 at 03:26
  • @cspurposesonly The official place to look is the C++ standard. But that costs money. There is a draft version available for free on the internet, but even so its not an easy read. Slightly easier is the cppreference.com web site, very informative and high quality but still perhaps too much for a beginner. But probably best is a good [C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282). – john Dec 14 '22 at 07:07
  • @cspurposesonly Why is a \n left in the stream after `cin >> a;`? The first answer is because \n is a whitespace character, and by definition `cin >> a` reads whitespace delimited values (this true if `a` is a string and also true for other types). But maybe you are asking why the rules are like that. I wouldn't know the answer to that as it's a design choice, and other choices could have been made. But having the `>>` operator read whitespace delimited tokens seems a natural enough decision to make. I hope that helps. – john Dec 14 '22 at 07:11
  • @cspurposesonly The other point to make is a general one. In C++ input streams are treated as a sequence of characters and a read position and that's it. Characters before the read position have been read, characters after the read position are yet to be read. This model applies to all input stream whether files or the console or something else. Most beginners start with the console (i,.e. `cin`) and it seems they usually have a more complex model in mind. They think that reading from `cin` is somehow synchronised with hitting the enter key. – john Dec 14 '22 at 07:18
  • @cspurposesonly So perhaps they think that any use of `cin >>` will reads up to the next enter key, but any excess input will be discarded, or something like that. None of this works, an input stream is a sequence of characters and a position within that stream called the read position. That's all there is too it. – john Dec 14 '22 at 07:20
  • @john I have one more question if you don't mind: `string a, b, c, d; cin >> a; cin >> b; cin >> c; cin.ignore(numeric_limits::max(), '\n'); getline(cin, d); cout << a << " " << b << " " << c << endl; cout << d << endl;` . This code works as I'd expect it to, but if I hit enter three times for a b c, wouldn't there be three '\n' in the input stream? So cin.ignore() would stop ignoring after it hits the first? Why does it have correct functionality then? –  Dec 14 '22 at 07:37
  • @cspurposesonly No because `>>` will skip (i.e. read and discard) whitespace **before** the string being read, it is only whitespace **after** the string that is unread. So take the case of `cin >> a >> b;` and you typing two \n. After `a` has been read the first \n will be unread, but when `b` is read that first \n will be read and discarded then `b` itself will be read and so only the second \n remains. – john Dec 14 '22 at 07:55
  • @cspurposesonly What you are suggesting would be very peculiar, in the stream model there is no way to read a character without all the preceding characters also being considered read. You can't move the sequence of characters around. Remember a sequence of characters and a read position, nothing else. As you type in a console the characters you type get added to the end of the sequence. But apart from that the sequence never changes. – john Dec 14 '22 at 07:56
  • @John sorry for the additional questions, but this is interesting to me. You say read position and sequence a lot. Does that mean that the previous input stream is still there (not discarded), but we've just moved past it (using the read position)? –  Dec 14 '22 at 08:43
  • @cspurposesonly Yes it does. And there exists a method to move the read position backwards or forwards (it's called `seekg`). However although this method exists, it's generally only used for files, it's unlikely to work on consoles. So these previous characters exist *conceptually* but in practise you might not be able to access them if you are reading from a console. This is another example how, as far as possible, C++ treats all streams the same. – john Dec 14 '22 at 09:16

1 Answers1

0

\n is left in the stream because when a user inputs something with std::cin, they hit enter and a '\n' char gets into the cin buffer. refer

Cause:

When consuming whitespace-delimited input (e.g. int n; std::cin >> n;) any whitespace that follows, including a newline character, will be left on the input stream. Then when switching to line-oriented input, the first line retrieved with getline will be just that whitespace. refer

Solutions:

  1. An explicit extraneous initial call to getline
  2. Removing consecutive whitespace with std::cin >> std::ws
  3. Ignoring all leftover characters on the line of input with
  4. cin.ignore(std::numeric_limitsstd::streamsize::max(), '\n');
Sidharth Mudgil
  • 1,293
  • 8
  • 25