GNU-getline:关于EOF的奇怪行为

Ton*_*ony 5 c linux eof

测试

为了找到getline()面对EOF 的行为,我写了以下测试:

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);
}
Run Code Online (Sandbox Code Playgroud)

而input1是:

abcCtrl-DEnter

结果:

 length 4: abc  //notice that '\n' is also taken into consideration and printed
Run Code Online (Sandbox Code Playgroud)

输入2:

abcEnter

完全相同的输出:

 length 4: abc
Run Code Online (Sandbox Code Playgroud)

似乎EOF被遗漏了getline()

源代码

所以我发现它的源代码getline()和后续内容是它的一个相关片段(我省略了一些注释和不相关的代码以简洁):

 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;
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

  • 为什么这里的长度是4(据我所知它应该是5)(正如维基说的那样,如果它不在一行的开头就不会是EOF)

一个类似的问题:伴随其他值的EOF行为,在该问题中注意getline()与GNU-getline不同

我使用GCC:(Ubuntu 4.8.2-19ubuntu1)4.8.2

maf*_*fso 3

Ctrl-D导致您的终端刷新输入缓冲区(如果\xe2\x80\x99t 尚未刷新)。否则,设置输入流的文件结束指示符。换行符也会刷新缓冲区。

\n

因此,您没有关闭流,而只是刷新了输入缓冲区,这就是为什么getline看不到文件结束指示器的原因。

\n

在这两种情况下,都不会接收文字EOT 字符(ASCII 0x04, ) (为此,您可以键入)。^DgetlineCtrl-VCtrl-D

\n

类型

\n
\n

abcCtrl-DCtrl-D

\n
\n

或者

\n
\n

abcEnterCtrl-D

\n
\n

实际设置文件结束指示器。

\n

来自POSIX

\n
\n

特殊字符

\n
    \n
  • EOF
  • \n
\n

输入上的特殊字符,如果ICANON设置了标志,则可以识别该字符。当接收到时,所有等待读取的字节立即传递给进程,而不等待<newline>,并且 EOF 被丢弃。因此,如果没有字节等待(即 EOF 发生在行的开头),则应从 中返回字节计数为零read(),表示文件结束指示。如果ICANON设置,则处理时 EOF 字符将被丢弃。

\n
\n

仅供参考,此处指定了 ICANON 标志。

\n