问题
Test
In order to find the behaviour of getline()
when confronted with EOF, I wrote the following test:
int main (int argc, char *argv[]) {
size_t max = 100;
char *buf = malloc(sizeof(char) * 100);
size_t len = getline(&buf, &max, stdin);
printf("length %zu: %s", len, buf);
}
And input1 is:
abcCtrl-DEnter
Result:
length 4: abc //notice that '\n' is also taken into consideration and printed
Input2:
abcEnter
Exactly same output:
length 4: abc
It seems that the EOF
is left out out by getline()
Source code
So I find the source code of getline() and following is a related snippet of it (and I leave out some comments and irrelevant codes for conciseness):
while ((c = getc (stream)) != EOF)
{
/* Push the result in the line. */
(*lineptr)[indx++] = c;
/* Bail out. */
if (c == delim) //delim here is '\n'
break;
}
/* Make room for the null character. */
if (indx >= *n)
{
*lineptr = realloc (*lineptr, *n + line_size);
if (*lineptr == NULL)
return -1;
*n += line_size;
}
/* Null terminate the buffer. */
(*lineptr)[indx++] = 0;
return (c == EOF && (indx - 1) == 0) ? -1 : indx - 1;
Question
So my question is:
- why length here is 4 (as far as I can see it should be 5)(as wiki says, It won't be a EOF if it not at the beginning of a line)
A similar question:EOF behavior when accompanied by other values but notice getline() in that question is different from GNU-getline
I use GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2
回答1:
Ctrl-D causes your terminal to flush the input buffer if it isn’t already flushed. Otherwise, the end-of-file indicator for the input stream is set. A newline also flushes the buffer.
So you didn't close the stream, but only flushed the input buffer, which is why getline
doesn't see an end-of-file indicator.
In neither of these cases, a literal EOT character (ASCII 0x04, ^D
) is received by getline
(in order to do so, you can type Ctrl-VCtrl-D).
Type
abcCtrl-DCtrl-D
or
abcEnterCtrl-D
to actually set the end-of-file indicator.
From POSIX:
Special characters
- EOF
Special character on input, which is recognized if the
ICANON
flag is set. When received, all the bytes waiting to be read are immediately passed to the process without waiting for a<newline>
, and the EOF is discarded. Thus, if there are no bytes waiting (that is, the EOF occurred at the beginning of a line), a byte count of zero shall be returned from theread()
, representing an end-of-file indication. IfICANON
is set, the EOF character shall be discarded when processed.
FYI, the ICANON flag is specified here.
来源:https://stackoverflow.com/questions/25423614/gnu-getline-strange-behaviour-about-eof