如何确定用fgets()读取的字符数?

Jam*_* Ko 3 c io stdio fgets

这是fgets()从手册页的描述:

char *fgets(char *s, int size, FILE *stream);
...

RETURN VALUE
  fgets() returns s on success, and NULL on error or  when  end  of  file
  occurs while no characters have been read.
Run Code Online (Sandbox Code Playgroud)

它不遵循模式read,在失败时返回-1,在成功时返回读取的字节数.相反,它返回char*NULL的失败和s成功.这没有给我任何关于输入多长时间的信息.所以,如果我有这样的事情:

char input_buffer[256];
fgets(input_buffer, sizeof(input_buffer), stdin);
Run Code Online (Sandbox Code Playgroud)

fgets调用之后,有没有办法告诉输入有多长没有先初始化缓冲区?

谢谢.

chu*_*ica 5

如何确定用fgets()读取的字符数?

char *fgets(char *s, int size, FILE *stream);
Run Code Online (Sandbox Code Playgroud)

strlen(s)检查fgets()返回值后使用.

if (fgets(s, size, stream)) {
  printf("number of characters that were read: %zu\n", strlen(s));
} else if (feof(stream)) {
  printf("number of characters that were read:0 End-of-file\n");
} else  {
  printf("number of characters that were read unknown due to input error\n");
}
Run Code Online (Sandbox Code Playgroud)

这工作,除非一个空字符 '\0'被解读为strlen()将遇到'\0'附加一个由函数之前.在这种情况下,strlen(s)之后fgets()会报告一个较小的值.

预先填充s然后调用有各种技巧 fgets(),但未定义未读缓冲区的其余部分会发生什么.存在其他缺点.

如果作为有效输入流的一部分的空字符是一个问题,请使用fgetc()或类似的东西getline().


空字符作为文本的常见方案是将文本编码为UTF-16.当然代码不应该fgets()用于阅读该文本,但这需要先验知识.由于错误地假设文本文件是非空字符文本文件,因此许多读取文本的代码以神秘的方式失败.

此外,即使文本文件被认为缺少空字符,以下代码会发生什么?

if (fgets(s, size, stream)) {
  size_t len = strlen(s);
  s[--len] = '\0';  // poor way to lop off the trailing \n, this could be UB
}
Run Code Online (Sandbox Code Playgroud)

这样的代码调用未定义行为与黑客攻击:一打滑空字符在开头的文件中的.(看到这个这个以获得更好的解决方案来消除潜力\n)

强大的代码不会假设文本格式正确并采取措施来检测异常.


迂腐:有fgets(char *s, int size, FILE *stream);一个病理问题size < 2.