c - fgets 在 Linux 和 Windows 中从同一个文件中写入不同的字符串
问题描述
我刚刚遇到一个问题,我在 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(";");
在 Windows 中:
String length: 14; Contents: 41 6e 64 72 65 6a 20 50 6c 61 76 6b 61 a ;
String length: 22; Contents: 41 6e 6e 61 20 4d 61 72 69 61 20 43 69 63 6d 61 6e 63 6f 76 61 a ;
String length: 25; 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 a ;
String length: 24; Contents: 4d 69 6c 61 6e 20 52 61 73 74 69 73 6c 61 76 20 50 6f 6b 6f 6a 6e 79 a ;
String length: 21; Contents: 4d 69 6c 65 6e 61 20 53 65 64 6d 69 6b 72 61 73 6b 6f 76 61 a ;
String length: 15; Contents: 56 69 6e 63 65 6e 74 20 53 69 6b 75 6c 61 a ;
String length: 17; Contents: 56 69 6e 63 65 6e 74 20 76 61 6e 20 47 6f 67 68 a ;
在 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 文本文件以 Linux 结尾'\r'
并且会犯规fgets()
。
进一步:读取具有"\r\n"
文本文件的文件,该文件期望"\n"
作为行尾序列,在读取完整缓冲区时会出现问题,并且在 next 上读取"......\r"
行剩余部分时会出现问题。每当缓冲区不足以容纳一行输入 时,就需要额外的处理来应对这种情况。"\n"
fgets()
一种变体的文本文件经常被复制到其他平台,因此这种情况并不罕见。
由于编辑,一些文本文件将混合行尾序列。
Pedantic 代码会将文件作为二进制文件读取并处理变体行结尾本身,而无需fgets()
. 祝你好运。
推荐阅读
- xcode - 使用新的 Apple 构建系统 (xcbuild) 时缺少 productTypeIdentifier 错误
- php - 在类似的测试中,PHP 7.4.8 比相同的 c++ 程序快 5.6 倍 (g++ 4.8.5)
- biztalk - 将消息传输到客户发送端口时 BizTalk AS2 发送端口错误
- android - 如何在 BOTH 表上获得一对多房间 Android 条件?
- javascript - 从 Promise 或 async / await 返回的值的数据类型
- android - 谷歌登录不适用于使用电容器生成的 ionic android 移动应用程序 - 抛出异常为 10
- reactjs - VS2019如何重启在本地构建时自动启动的npm
- android - 如何在对话框选择器中显示选定的日期?
- python-3.x - 得到 TypeError: Expected int32, got None of type 'NoneType' 相反
- .net - 在 .NET 正则表达式中,将零宽度正前瞻断言与其他搜索词结合起来