为什么我们在 C 编程中总是必须使用 fgetc 命令而不是 fscanf 命令,它做同样的事情但打印出奇怪的结果?

Why we always have to use fgetc command in C programming instead of fscanf which do the same thing but prints strange results?

在 C 编程中,每当我使用 fgetc(file) 读取所有字符直到文件末尾时,它就可以工作。但是当我使用类似的 fscanf(file, "%c") 函数时,它会打印出奇怪的字符。 代码:

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

int main() {
    char c;
    FILE * file = fopen("D\filename.txt", "r");
    while (c != EOF) {
        fscanf(file, "%c", &c);
        printf("%c", c);
    }
    return 0;
}

但是当我使用 fgetc 而不是 fscanf 时,它起作用了。它打印文件中存在的每个字符。

谁能回答为什么会这样?

注意

c=fscanf(file,"%c");

is undefined behavior (here I am explaining why you should be afraid of it, even when a program seems to apparently "work"), and every good C compiler (e.g. GCC to be invoked as gcc -Wall -Wextra -g) 应该警告你(如果你启用所有警告)。在用 C 编写代码时,您还应该学习如何使用调试器(例如 gdb)。

您应该阅读 fscanf(3) 的文档。你可能想编码

char c= '[=11=]';
if (fscanf(file, "%c", &c) <= 0) break;

你最好养成初始化每个变量的习惯;一个好的优化编译器会删除无用的初始化,否则会经常警告您有关单元化变量的信息。

请注意,在您的情况下使用 fgetc(3) 可能更可取。 然后你需要声明 c 为整数,而不是字符,代码:

do {
  int c=fgetc(file);
  if (c==EOF) break;
} while (!feof(file));

注意在上面的循环中 feof(file) 永远不会为真(因为 fgetc 之前会给出 EOF),所以你最好替换 while(!feof(file)) while(true)

使用相同的代码更容易阅读(其他开发人员,甚至你自己在几个月后),而且很可能更快。 fscanf 的大多数实现都以某种方式基于 fgetc 或非常相关的东西。

此外,养成测试输入的好习惯。输入文件可能与您预期的不同。

在大多数最新的系统上,编码是今天 UTF-8. Be aware that some (human language) characters could be encoded in several bytes (e.g. French accentuated e letter é, or Russian yery letterЫ, or even the Euro sign , or the mathematical for all sign , letters or glyphs in other languages, etc....). You probably should consider using some UTF-8 library (e.g. libunistring)如果你关心它(你应该关心严肃软件中的 UTF-8!)。

Nota Bene:如果您还年轻并且正在学习编程,最好(恕我直言)在学习 C 或 Java 之前先学习 Scheme with SICP, using e.g. Racket。 C真的不适合初学者恕我直言。

PS 字符类型(通常是一个字节)是 char 小写。