[英]carriage return by fgets
我正在运行以下代码:
#include<stdio.h>
#include<string.h>
#include<io.h>
int main(){
FILE *fp;
if((fp=fopen("test.txt","r"))==NULL){
printf("File can't be read\n");
exit(1);
}
char str[50];
fgets(str,50,fp);
printf("%s",str);
return 0;
}
text.txt 包含: I am a boy\\r\\n
由于我在 Windows 上,它需要 \\r\\n 作为换行符,所以如果我从文件中读取它应该在str
存储"I am a boy\\n\\0"
,但我得到"I am a boy\\r\\n"
。 我正在使用 mingw 编译器。
该行为取决于 c 库实现以及您传递给fopen
模式。 请参阅有关fopen
的 MSDN 文档中的引用(MSDN 上的fopen
) :
b - 以二进制(未翻译)模式打开; 禁止涉及回车和换行符的翻译。
意思是,如果您使用 Microsoft c 库,并打开省略 'b' 的文件,则回车字符将从流中删除。
由于您使用的是 mingw,您的编译器可能会链接到遵循 POSIX 标准的 GNU c 库。 这是 GNU 文档关于fopen
(gnu.org 上的 fopen)的说明:
opentype 中的字符 'b' 具有标准含义; 它请求二进制流而不是文本流。 但这在 POSIX 系统(包括 GNU 系统)中没有区别。
结论:您省略了 'b' 模式字符,它以文本模式打开您的流。 您在 Windows 上,但使用 GNU c 库,它在文本和二进制模式之间没有区别。 这就是fgets
读取回车和换行的原因。
由于我在 Windows 上,它需要 \\r\\n 作为换行符......
这个假设是错误的。 C 标准将回车和换行视为两种不同的事物,如 C99 §5.2.1/3(字符集)所示:
[...] 在基本执行字符集中,应该有代表警告、退格、回车和换行的控制字符。 [...]
fgets
函数描述如下,在 C99 §7.19.7.2/2 中:
fgets 函数从 stream 指向的流中读取至多比 n 指定的字符数少 1 到 s 指向的数组中。 在换行符(保留)后或文件结束后不会读取其他字符。 在读入数组的最后一个字符后立即写入空字符。
因此,当遇到字符串I am a boy\\r\\n
,符合要求的实现应该读到\\n
字符。 实现应该基于平台丢弃\\r
没有可能合理的理由。
c 标准对以下内容中的文本流进行了说明(除其他外):
可能必须在输入和输出中添加、更改或删除字符,以符合在宿主环境中表示文本的不同约定。 因此,流中的字符与外部表示中的字符之间不需要一一对应。 仅在以下情况下,从文本流中读取的数据将必然与之前写入该流的数据相等: 数据仅由打印字符和控制字符水平制表符和换行符组成; 没有新行字符紧跟在空格字符之前; 最后一个字符是换行符。
换句话说,如果文件以文本模式打开,则实现可以自由地添加、删除和修改控制字符,如果它在往返磁盘时需要/需要。 这显然是微软实现对回车所做的,但 gnu 实现没有。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.