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

时间:2014-08-21 10:09:06

标签: 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);
}

而input1是:

  

a b c Ctrl-D 输入

结果:

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

输入2:

  

a b c 输入

完全相同的输出:

 length 4: abc

EOF 似乎忽略了getline()

源代码

所以我发现source code of 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;

问题

所以我的问题是:

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

一个类似的问题:EOF behavior when accompanied by other values但请注意该问题中的 getline()与GNU-getline不同

  

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

1 个答案:

答案 0 :(得分:3)

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

所以你没有关闭流,但只刷新输入缓冲区,这就是getline没有看到文件结束指示符的原因。

在这两种情况下,^D都收到了文字EOT 字符(ASCII 0x04,getline)(为了这样做,你可以输入 Ctrl-V Ctrl-D )。

类型

  

B'/ KBD> C CTRL-d CTRL-d

  

B'/ KBD> C 输入 CTRL-d

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

来自POSIX

  

特殊字符

     
      
  • EOF
  •   
     

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

仅供参考,ICANON标志指定为here