使用特定字节序列时获得早期 EOF

getting early EOF when using specific sequence of bytes

提问人:Makalone LOgman 提问时间:11/12/2023 最后编辑:Ken WhiteMakalone LOgman 更新时间:11/17/2023 访问量:61

问:

我有这个示例程序,它只是读取 stdin 并将字符打印为 ints:

#include <stdio.h>

int main() {
    while (1) {
        char c = getchar();
        printf("%i\n", c);
        if (feof(stdin)) return 0;
    }
}

我还使用此 Python 脚本生成了输入数据:

data = [71, 69, 71, 121, 118, 81, 51, 98, 51, 114, 119, 114, 108, 120, 33, 40, 22, 122, 125, 97, 88, 20, 81, 9, 22, 70, 70, 75, 89, 89, 90, 90, 88, 126, 20, 70, 9, 22, 77, 69, 71, 20, 70, 9, 22, 102, 78, 25, 103, 120, 124, 93, 102, 65, 30, 122, 96, 90, 20, 81, 9, 22, 91, 68, 31, 92, 105, 111, 20, 70, 9, 22, 99, 68, 124, 94, 97, 76, 17, 68, 89, 90, 20, 70, 9, 22, 76, 97, 91, 66, 105, 69, 20, 70, 9, 22, 16, 100, 20, 81, 9, 22, 77, 26, 93, 25, 111, 100, 64, 99, 20, 70, 9, 22, 73, 111, 79, 107, 102, 80, 127, 110, 28, 26, 108, 20, 70, 9, 22, 28, 93, 120, 75, 106, 124, 88, 76, 102, 78, 80, 24, 122, 20, 70, 9, 22, 121, 90, 78, 67, 73, 67, 20, 81, 9, 22, 90, 27, 76, 90, 20, 81, 9]

with open('data', 'wb') as f:
  f.write(bytes(data))

从 Visual Studio 编译或运行它后:cl.exetcc

cat data | ./out.exe

输出结尾为:

9
22
77
-1

它只是在输入数据的中间。此外,输出行数应为 165,但仅为 105 行。

此示例在 Linux 或具有不同输入的 Windows 上工作得很好。 为什么这在这个特定数据上失败?我做错了什么?

c Windows CL TCC

评论

6赞 Some programmer dude 11/12/2023
在 Windows 上,字节值对应于文本输入的文件结束序列。26Ctrl-Z
0赞 Makalone LOgman 11/12/2023
我以为CTRL-Z只是由控制台/终端解释的,而不是由程序解释的。
4赞 Some programmer dude 11/12/2023
在使用 MSVC 运行时的 Windows 上不行。您需要以其他方式读取输入,绕过其文本模式,以某种方式读取原始二进制数据。stdin
3赞 Some programmer dude 11/12/2023
另一方面,请记住 getchar 实际上返回一个 .如果您想以可移植和标准的方式根据值检查结果,这一点至关重要。intintEOF
1赞 Weather Vane 11/12/2023
...请注意,您在响应 之前打印了输入值,这表示您尝试读取文件末尾。因此,MS 不认为这些数据是数据。feof()26

答:

3赞 Mark Adler 11/12/2023 #1

您可以转换为二进制:stdin

#include <stdio.h>

#ifdef _WIN32
#  include <fcntl.h>
#  include <io.h>
#  define BINARY(fd) _setmode(fd, _O_BINARY)
#else
#  define BINARY(fd)
#endif

int main(void) {
    BINARY(0);
    int ch;
    while ((ch = getchar()) != EOF)
        printf("%i\n", ch);
    return 0;
}

请注意,这只是故意破坏数据的恶意操作系统上的问题。请参见 .#ifdef

评论

0赞 Mark Ransom 11/12/2023
我认为有必要在第一次使用该文件之前调用,就像您在示例中所做的那样。_setmode