From what I've read, the Linux terminal (in default settings) buffers the input and only sends it after receiving either EOF
or '\n'
.
When I loop c = getchar();
and check each c
for being EOF
(end then break) I need to do CTRL-D twice in order to stop reading, as the first EOF
is always consumed by the terminal (I know one can change the terminal to raw, but maybe this is a bit overkill).
However, when I check for c
being '\n'
(which also sends the input) it will not be consumed.
Example:
'a'
,'b'
,'c'
,'\n'
'a'
,'b'
,'c'
'a'
,'b'
,'c'
,EOF
'a'
,'b'
,'c'
,'\n'
,EOF
Isn't this highly inconsistent? Or is there any rationale behind it?
I want to parse input including whitespaces and thus cannot check for '\n'
but for EOF
- is that possible without changing the terminal to raw?
I've tried with feof(stdin)
too, but apperently this doesn't work either :/
That's not how it works. ^D
sends on the currently buffered line, so if you don't hit it immediately after a newline, your program will not see an empty read and will not know the input is ended. So you need another ^D
to send nothing. But your program never sees a ^D
.
In fact you can use stty
to change the terminal's EOF
character, so that for example ^N
will end the input; your program will run exactly the same, because it does not depend of the value of the EOF keyboard character.
PS. Since you were trying to write a C program: the input calls return EOF
when they try to read a file, and get an empty buffer (0 characters). In fact, EOF
is not ^D
as you imagine, but -1
: This value was chosen because it does not fit in a byte, while read()
could legally return any possible byte (yes, even '\04' aka ^D
). This is why the signature of getchar()
says it returns an int
.