繁体   English   中英

fgets 回车

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM