打印文件内容,但在 Linux 上无限打印一堆问号

Printing contents of file but prints a bunch of question marks infinitely on Linux

提问人:Jay 提问时间:9/4/2023 最后编辑:chqrlieJay 更新时间:9/4/2023 访问量:66

问:

我正在尝试制作一个打印文件内容的程序,但每当我尝试运行它时,它只会无限打印一堆问号,这只有在我在 UTM 虚拟机(Linux 终端)上运行它时才会发生。当我在Mac终端上运行它时,它工作正常,所以我不确定它是否与虚拟机或我的程序有关。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    // input from user
    if (argc != 2) {
        printf("Too many/no arguments!\n");
        exit(1);
    }
    char *fname;
    fname = argv[1];
    // Open file
    FILE *fdin = fopen(fname, "r");
    char ch = fgetc(fdin);
    while (ch != EOF) {
        printf("%c", ch);
        ch = fgetc(fdin);
    }
    fclose(fdin);
    return 0;
}

图像:output/result

文本文件只是输入 .txt,内容是:

HELLOOO!!

但它无限地打印了一堆问号。在我的Mac终端(M1)上运行良好,并且打印正常,没有错误。它只是在我的UTM虚拟机(Linux)上不起作用HELLOOO!!

C Linux 文件

评论

0赞 dbush 9/4/2023
尝试将 的类型更改为 。chint
0赞 Some programmer dude 9/4/2023
请注意,fgetc 返回一个 int.与值相比,这一点相当重要。intEOF
0赞 Jay 9/4/2023
@dbush 它奏效了!谢谢!!但是你知道为什么它在我的 Mac 终端上工作吗,即使 ch 的类型是 char 并且它不能在 Linux 终端上运行?
0赞 Barmar 9/4/2023
一些编译器默认为 signed,而另一些编译器则默认为 .当它未签名时,始终为 true,并且您继续读取文件末尾。charunsignedch != EOF
0赞 Some programmer dude 9/4/2023
问题在于它是一种特殊类型,与任何其他整数类型不同,可以是有符号的,也可以是无符号的。由编译器决定,即使在不同系统(或同一系统上的不同编译器)上使用相同的编译器时,也可能有所不同。如果为 unsigned,则该值实际上是 。这与值不同。charchar-1255-1intEOF

答:

1赞 0___________ 9/4/2023 #1

你的问题很常见。 返回是有原因的。fgetcint

您需要声明为 notchintchar

int ch = fgetc(fdin);
2赞 chqrlie 9/4/2023 #2

您声明为 .该类型无法存储 返回的所有值。chcharcharfgetc()

  • 如果是有符号类型,则 和 (或 ) 都具有值,并且在文件末尾的 test 为 true,并且如果文件包含设置了所有位的字节,则 TRUE 也是如此。 在 Mac 上签名为默认值,因此程序在此系统上的行为符合预期,但如果文件包含字节,则无法输出完整的文件内容。charEOF'\377''\xff'-1ch == EOFchar'\377'

  • 如果 是 unsigned 类型,则返回 ,即 : 时,此值将转换为 an 并成为 ,与 不同,因此测试永远不会为 true,程序会无限期地打印该字符。linux 终端需要 UTF-8 编码的输出,因此该字符是无效字符,并显示为问号。这解释了 linux 上的行为。charfgetc(fdin)EOF-1unsigned char255EOFwhile (ch != EOF)'\xff''\xff'

将 的类型更改为 以解决此问题,并在两个目标体系结构上获得可靠的操作。chint

这是一个修改后的版本:

#include <errno.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    // input from user
    if (argc != 2) {
        fprintf(stderr, "invalid number of arguments\n");
        return 1;
    }
    char *fname = argv[1];
    // Open file
    FILE *fdin = fopen(fname, "r");
    if (fdin == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno));
        return 1;
    }
    int ch;
    while ((ch = fgetc(fdin)) != EOF) {
        putchar(ch);
    }
    fclose(fdin);
    return 0;
}