C Fgets在Linux和Windows中从同一文件写入不同的字符串
我刚刚遇到一个问题,我在Linux中的valgrind和Windows cmd中的其他测试之间跳了起来 我正在从这样一个文件中读取某一行:C Fgets在Linux和Windows中从同一文件写入不同的字符串,c,linux,fgets,C,Linux,Fgets,我刚刚遇到一个问题,我在Linux中的valgrind和Windows cmd中的其他测试之间跳了起来 我正在从这样一个文件中读取某一行: fgets(buf, MAX_LINE_LEN, f_input); 当然,buf是MAX_LINE_LEN+1的大小,但我离题了 这是 printf("String length: %u; Contents: ", strlen(buf)); for (usint i = 0; i < strlen(buf); i++) printf("%x
fgets(buf, MAX_LINE_LEN, f_input);
当然,buf是MAX_LINE_LEN+1的大小,但我离题了 这是
printf("String length: %u; Contents: ", strlen(buf));
for (usint i = 0; i < strlen(buf); i++)
printf("%x ", buf[i]);
puts(";");
在Linux中:
String length: 15; Contents: 41 6e 64 72 65 6a 20 50 6c 61 76 6b 61 d a ;
String length: 23; Contents: 41 6e 6e 61 20 4d 61 72 69 61 20 43 69 63 6d 61 6e 63 6f 76 61 d a ;
String length: 26; Contents: 4d 61 72 69 61 20 52 61 7a 75 73 6f 76 61 20 4d 61 72 74 61 6b 6f 76 61 d a ;
String length: 25; Contents: 4d 69 6c 61 6e 20 52 61 73 74 69 73 6c 61 76 20 50 6f 6b 6f 6a 6e 79 d a ;
String length: 22; Contents: 4d 69 6c 65 6e 61 20 53 65 64 6d 69 6b 72 61 73 6b 6f 76 61 d a ;
String length: 16; Contents: 56 69 6e 63 65 6e 74 20 53 69 6b 75 6c 61 d a ;
String length: 18; Contents: 56 69 6e 63 65 6e 74 20 76 61 6e 20 47 6f 67 68 d a ;
正如您在Linux中看到的,NL前面还有一个字符,即回车符。如果有人能解释这一点,让我省去为Linux和Windows代码添加
ifdef
语句的痛苦,我将不胜感激。我知道,linux在每一行后面都附加了一个回车符,但是当它被fgets
读取时,这真的是预期的行为吗?MS并且linux对文本文件行结尾有不同的期望:“\r\n”
vs“\n”
为了应对,建议在fgets()
之后使用strcspn()
删除潜在的行尾序列,无论是“\n”
,“\r\n”
还是缺失
fgets(buf, MAX_LINE_LEN, f_input);
buf[strcspn(buf, "\n\r")] = '\0';
Windows上的某些编译器将使用
“\n”
作为行尾序列,而其他编译器则使用“\r\n”
。因此,我把这种变化归因于编译器及其制造商,而不是操作系统。还有一些旧的MAC文本文件以'\r'
结尾,在Linux上会破坏fgets()
进一步:当在下一个fgets()
上读取完整缓冲区为“…\r”
而将行剩余部分为”\n“
时,将具有“\r\n”
的文件读取为预期作为行尾序列的文本文件会出现问题。当缓冲区不足以容纳一行输入时,需要进行额外的处理
一种变体的文本文件通常会复制到其他平台,因此这种情况并不罕见
由于编辑,某些文本文件将混合使用行尾序列
Pedantic代码将以二进制形式读取文件,并自行处理变量行结尾,而不使用
fgets()
。祝你好运。MS和Linux对文本文件行结尾有不同的期望:“\r\n”
vs“\n”
为了应对,建议在fgets()
之后使用strcspn()
删除潜在的行尾序列,无论是“\n”
,“\r\n”
还是缺失
fgets(buf, MAX_LINE_LEN, f_input);
buf[strcspn(buf, "\n\r")] = '\0';
Windows上的某些编译器将使用
“\n”
作为行尾序列,而其他编译器则使用“\r\n”
。因此,我把这种变化归因于编译器及其制造商,而不是操作系统。还有一些旧的MAC文本文件以'\r'
结尾,在Linux上会破坏fgets()
进一步:当在下一个fgets()
上读取完整缓冲区为“…\r”
而将行剩余部分为”\n“
时,将具有“\r\n”
的文件读取为预期作为行尾序列的文本文件会出现问题。当缓冲区不足以容纳一行输入时,需要进行额外的处理
一种变体的文本文件通常会复制到其他平台,因此这种情况并不罕见
由于编辑,某些文本文件将混合使用行尾序列
Pedantic代码将以二进制形式读取文件,并自行处理变量行结尾,而不使用fgets()
。祝你好运
正如您在Linux中看到的,NL前面还有一个字符,即回车符
这是因为您的文件使用CR+LF换行符,即每个换行符实际上是两个字符:“\r\n”
如果在Windows中打开文件时不带“b”
标志,则其C库会将您写入\r\n
的每个\r\n
转换为\n
在Windows中使用“b”
fopen()标志查看实际的文件内容
当您使用fgets(buf,sizeof buf,handle)
读取一行时,您可以使用buf[strcspn(buf,“\r\n”)]='\0'
删除换行符
正如您在Linux中看到的,NL前面还有一个字符,即回车符
这是因为您的文件使用CR+LF换行符,即每个换行符实际上是两个字符:“\r\n”
如果在Windows中打开文件时不带“b”
标志,则其C库会将您写入\r\n
的每个\r\n
转换为\n
在Windows中使用“b”
fopen()标志查看实际的文件内容
当您使用
fgets(buf,sizeof buf,handle)
读取一行时,您可以使用buf[strcspn(buf,“\r\n”)]='\0'
删除换行符。在C中,您可以以文本或二进制模式打开文件流。在二进制模式下,不进行转换,输入和输出是文件中的字节。在文本模式下,C“换行符”字符被转换为相关平台上的通用字符。在类UNIX系统中,这是一个0A
字节,在类DOS系统中,这是一个0D
字节,后跟一个0A
字节。以下列出了其他操作系统上的其他情况:
因此,您不必处理每个程序中的每种不同的文本格式,所有这些格式都将被转换为C程序在默认情况下(文本模式)看到的
\n
字符。输入/输出层为您进行必要的翻译
当您使用C打开文件流进行读写时,您提供了一个“文件模式”参数—您可能在这里将其用作
“r”
来读取文件,或“w”
来写入文件。如果要完成换行翻译,可以指定以二进制模式打开流,使用“rb”
进行读取或“wb”
进行写入。在C中,可以以文本或二进制模式打开文件流。在二进制模式下,没有trans