3

Executing the command:

./program < input.txt

with the following code checking:

string input;
while(cin) {
  getline(cin, input);
}

The above code seems to generate an extra getline() call where input is empty. This happens regardless of whether or not there's a \n on the last line of input.txt.

Lazer
  • 90,700
  • 113
  • 281
  • 364
Christopher Dorian
  • 2,163
  • 5
  • 21
  • 25

3 Answers3

7

@Jacob had the correct solution but deleted his answer for some reason. Here's what's going on in your loop:

  1. cin is checked for any of the failure bits (BADBIT, FAILBIT)
  2. cin reports no problem because nothing has yet been read from the file.
  3. getline is called which detects end of file, setting the EOF bit and FAILBIT.
  4. Loop executes again from 1, except this time it exits.

You need to do something like this instead:

std::string input;
while(std::getline(std::cin, input))
{
     //Have your way with the input.
}
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • @Billy ONeal, I undeleted it. – Jacob Relkin Nov 28 '10 at 05:53
  • 1
    @Billy - have a look at the documentation [operator!()](http://www.cplusplus.com/reference/iostream/ios/operatornot/) only checks for BADBIT or FAILBIT -- not EOF. The OP's problem stems from the fact that, when EOF is reached normally, neither BADBIT nor FAILBIT are set -- only EOF. So the loop runs again -- `getline()` attempts to read a stream at EOF, and *fails*, thus setting FAILBIT. Thus, the loop exits. Your solution will work, but your explanation is incorrect. – Lee Nov 28 '10 at 05:54
  • @Lee: Agreed. Fixed. @Jacob: +1 to you. (Though @Lee, cplusplus.com has a few errors which has led me to not trust it as an authoritative source any longer. However, the standard seems to agree in this case :) ) – Billy ONeal Nov 28 '10 at 06:05
  • @Billy - +1 for fix. ..and agreed that cplusplus.com has errors. I'd love to find a well-indexed alternative that has less issues. Any suggestions? – Lee Nov 28 '10 at 06:13
  • @Lee [Apache's](http://stdcxx.apache.org/doc/stdlibref/noframes.html) reference and [cppreference.com](http://cppreference.com/) are both more accurate than cplusplus.com in my experience. However, both do have inaccuracies. I tend to suggest the [Josuttis](http://www.amazon.com/dp/0201379260/) book as an alternative. – fow Nov 28 '10 at 09:18
  • oops, it was @fow that left he links. @Billy, sorry for the confusion. – Lee Nov 28 '10 at 18:34
3

How about this:

string input;
while(getline(cin, input)) {
  //do something with input...
}
Jacob Relkin
  • 161,348
  • 33
  • 346
  • 320
2

EDIT: please note, in the example below, I show you "how to detect EOF". As @Billy has pointed out, you probably want to use good() instead of eof() to detect any error condition or eof. I had included information about this at the end of my answer, but it's important, so I'm adding this note at the top to ensure that it's clear.

(original answer follows)


You want this:

string input;
while( !cin.eof() ) {
   getline(cin, input);
}

using operator! on an iostream only checks whether a failure or other error condition has occurred. ios::operator!().

You can use good() in place of !eof() to check for any of the conditions eof, badbit, or failbit. ios::good().

Lee
  • 13,462
  • 1
  • 32
  • 45
  • Sorry, but looping checking for EOF is never the correct answer. The loop should be written in terms of `good`, not in terms of `eof`. Most importantly, it still fails in the OP's test case (i.e. `cin` hasn't reached EOF yet because nobody's tried to read from it) Finally, the OP never used `operator!` in his or her code. – Billy ONeal Nov 28 '10 at 05:43
  • @Billy - did you read the entire answer!? I suggested use of `good()` instead of `eof()`. The original question was "Detecting EOF in C++..."... My answer makes clear the difference between all the conditions, and clearly explains why the OP's problem is occurring, and how to fix it. I hope that wasn't worth a down vote. – Lee Nov 28 '10 at 05:48
  • Yes, I did read the entire answer. But the assertion that "this is what you want" isn't right -- the code posted is *not* what the OP wants, the code posted is wrong and will result in an infinite loop on failure. – Billy ONeal Nov 28 '10 at 05:52
  • I had a direct `cin>>n;` instead of `getline()`, so this solution worked great. Thanks. – Manohar Reddy Poreddy Nov 19 '20 at 02:03