C GNU getline:关于EOF的奇怪行为 试验

C GNU getline:关于EOF的奇怪行为 试验,c,linux,eof,C,Linux,Eof,为了找到遇到EOF时getline()的行为,我编写了以下测试: 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); } 输入1是: abcCtrl登特 结果:

为了找到遇到EOF时
getline()
的行为,我编写了以下测试:

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);
}
输入1是:

abcCtrl登特

结果:

 length 4: abc  //notice that '\n' is also taken into consideration and printed
输入2:

abcEnter

完全相同的输出:

 length 4: abc
似乎
EOF
getline()

源代码 因此,我发现,以下是其中的一个相关片段(为了简洁起见,我省略了一些注释和不相关的代码):

问题: 所以我的问题是:

  • 为什么这里的长度是4(据我所知应该是5)(如前所述,如果不是在一行的开头,它就不会是EOF)
一个类似的问题:但是请注意,这个问题中的getline()与GNU getline不同

我使用GCC:(ubuntu4.8.2-19ubuntu1)4.8.2

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

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

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

类型

abcCtrl-DCtrl-D

abcEnterCtrl-D

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

发件人:

特殊字符

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


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

任何关于“Ctrl-D导致终端刷新输入缓冲区”的引用?此外,维基百科说,“驱动程序将一行开头的Control-D字符转换为文件结尾的指示符。”这是错误的吗?似乎是正确的。如果运行
cat
,在不按enter键的情况下键入一些文本,然后按^D,
cat
将立即回显您目前键入的内容。不幸的是,没有。我找到了,尽管没有引用。你从维基百科上引用的话没有错(也没有反驳我),只是不完整。它没有说明如果未在行首按
^D
会发生什么情况。注意:如果使用转义约定的实用程序在转义后立即检测到文件结束条件,则结果未指定。没什么帮助,但似乎是POSIX指定了
^D
。但是我找不到它。这些问题经常出现在这里,我发现的所有副本也都没有引用来源(而且大多数根本没有提到当不是在行首按下
^D
时会发生什么)。如果我们能找到它的来源/具体位置,那就太好了。我想我们同意。查看my
/a.out作为测试,使用程序的二进制文件作为自己的输入:
/a.out在这里查看我的答案:有关终端如何处理“特殊”字符的演示(它是关于^C,而不是^D,但机制类似)
len
是4,因为(
a
+
b
+
C
+
+
+
\n
=
4
). 无需使用
ctrl+d
。只需
abc[enter]
@wildplasser很抱歉这么晚了。谢谢你能详细解释一下你是如何得出这个结论的吗?因为我没有弄明白。大部分结论都在@mafso中。我的重点是:没有EOF字符。这里(有时)有一个EOF条件,它有时被转换成一个值为EOF的int。mafso的反应涵盖了这种反应延迟的情况(通过终端/终端驱动程序/原始输入和程序之间的缓冲)
 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;