2

The following code simply echoes the standard input to the standard output. If I run the program like so ./a.out, I can type anything and the program works fine. However, if I run it like this ./a.out < input.txt I get an infinite loop, regardless of the content of input.txt.

#include <iostream>

using namespace std;

int main() {
  string input;
  while (true) {
    cout << "Type your input: ";
    getline(cin, input);
    cout << input << endl;
  }
  return 0;
}

What am I doing wrong?

EDIT: To clarify, I expect that after the input from the input file is finished, getline waits for more input from stdin. Instead, it continues to read when nothing is there.

gsgx
  • 12,020
  • 25
  • 98
  • 149
  • And why do you expect it to end? `while (true)...` is always true, so it always loops... *forever* – Cornstalks Oct 14 '12 at 02:51
  • I expect it to wait for input, which it ends up not receiving. – gsgx Oct 14 '12 at 02:55
  • 4
    Redirection doesn't work like that. [Here's something to read](http://technet.microsoft.com/en-us/library/bb490982.aspx). Notably: "`<`: Reads the command input from a file, instead of reading input from the keyboard." Using `<` makes it so the keyboard is ignored and the file is treated as input. There's no "switching over" when the end of the file is reached either. – Cornstalks Oct 14 '12 at 02:58
  • @Cornstalks Thanks, that clears things up. – gsgx Oct 14 '12 at 03:00

3 Answers3

1

Your loop has no terminating condition, be it a break, or right inside the while part. Instead, you probably want this:

while (getline(cin, input))

That will end when the input fails, most likely resulting from having reached EOF.

chris
  • 60,560
  • 13
  • 143
  • 205
1

You don't have a terminating condition for your loop: while (true) is an infinite loop in any case - that is, without a break/exit/etc. in the loop body.

I'm guessing that when using your program to echo stdin you end it by pressing Ctrl-C. Run your program using ./a.out, and type Ctrl-D (EOF): you'll also get an infinite loop.

Look over the docs for getline: use the return value to end your loop:

while (getline(cin, input))
pb2q
  • 58,613
  • 19
  • 146
  • 147
  • Whoa, didn't know that thing about Ctrl-D. Anyway, I expected getline to pause when there was no more input and wait for more, but I guess what you're saying is getline just gets an empty string when it reaches the end of a file. – gsgx Oct 14 '12 at 02:59
  • 1
    @gsingh2011 check out [this question](http://stackoverflow.com/questions/2251433/checking-for-eof-in-stringgetline): you need a terminating condition for your loop – pb2q Oct 14 '12 at 03:02
0

What you're doing wrong is that you ignore the result of an input operation, in this case getline.

You must never ignore the result of an input operation. It is always a programming error to do so. You cannot know or make assumptions about the state of external data, so you must always check whether an input operation succeeded. If it does not, then it is generally an error to access the purported input variable for reading, so you really need to check every time, and before accessing the result.

In the present case, std::getline returns a reference to the stream object, and you can evaluate the stream as a boolean. It evaluates as true if and only if the extraction succeeded; otherwise, you must not use the result (and presumably stop reading).

All in all, the code should go like this:

for (std::string line; std::getline(std::cin, line); )
{
    // use "line"
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084