2

When I run the code below, I use three inputs (in Ubuntu terminal):

  1. abc(Ctrl+D)(Ctrl+D)
  2. abc(Ctrl+D)(Enter)(Ctrl+D)
  3. abc(Enter)(Ctrl+D)

The code reacts well in all cases. My question is: why in 1) and 2) I need two EOF?

#include <iostream>

int main()
{
  int character;

  while((character=std::cin.get())!=EOF){}

  std::cout << std::endl << character << std::endl;

}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
Vito
  • 23
  • 2
  • 1
    You're making unfounded assumptions about what Ctrl+D does. – Lightness Races in Orbit Jun 07 '15 at 04:07
  • http://unix.stackexchange.com/questions/110240/why-does-ctrl-d-eof-exit-the-shell – William Pursell Jun 07 '15 at 04:08
  • There are many questions about this, including [Why does `getchar()` recognize EOF only in the beginning of a line?](http://stackoverflow.com/questions/14436596/why-does-getchar-recognize-eof-only-in-the-beginning-of-a-line). And also the question I've closed this as a duplicate of. – Jonathan Leffler Jun 07 '15 at 04:54

2 Answers2

4

You don't have "two EOF". Bash is putting the tty in raw mode, and interpreting ^D differently depending on context. If you type ^D after a newline, bash closes the input stream on the foreground process. If you type a few characters first, bash requires you to type ^D twice before doing so. (The first ^D is treated like 'delete')

William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • 1
    @rici Your explanation is absolutely needed, because my answer is completely wrong. Bash puts the tty in raw mode while it is taking commands, but it puts the tty back in canonical mode to run a command. – William Pursell Jun 07 '15 at 04:37
4

That's how the "EOF" character works (in "canonical" mode input, which is the default). It's actually never sent to the application, so it would be more accurate to call it the EOF signal.

The EOF character (normally Ctrl-D) causes the current line to be returned to the application program immediately. That's very similar to the behaviour of the EOL character (Enter), but unlike EOL, the EOF character is not included in the line.

If the EOF character is typed at the beginning of a line, then zero bytes are returned to the application program (since the EOF character is not sent). But if a read system call returns 0 bytes, that is considered an end-of-file indication. So at the beginning of a line, an EOF will be treated as terminating input; anywhere else, it will merely terminate the line and so you need two of them to terminate input.

For more details, see the .Posix terminal interface specification.

rici
  • 234,347
  • 28
  • 237
  • 341