C Fgets在Linux和Windows中从同一文件写入不同的字符串

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

我刚刚遇到一个问题,我在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 ", 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