为什么每当我尝试从 txt 文件中读取不可打印的字符时,C 中的 fgetc() 总是读取额外的、不存在的字符?



我正在尝试从文本文件中读取不可打印的字符,打印出字符的ASCII代码,最后将这些不可打印的字符写入输出文件。

但是,我注意到,对于我阅读的每个不可打印的字符,在我真正想阅读的内容前面总会存在一个额外的不可打印字符。

例如,我想读的字符是"§"。 当我在我的程序中打印出它的 ASCII 代码时,它打印出的不是只打印"167",而是打印出"194 167"。

我在调试器中查找了它,并在 char 数组中看到"§"。但是我的输入文件中没有任何地方。 调试器的屏幕截图

在我将不可打印的字符写入输出文件后,我注意到它也只是"§",而不是"§"。

我读到的每个不可打印的字符上都附加了一个额外的字符。为什么会这样?我该如何摆脱它?

谢谢!

代码如下:

case 1:
mode = 1;
FILE *fp;
fp = fopen ("input2.txt", "r");
int charCount = 0;
while(!feof(fp)) {
original_message[charCount] = fgetc(fp);
charCount++;
}
original_message[charCount - 1] = '';
fclose(fp);
k = strlen(original_message);//split the original message into k input symbols
printf("k: n%lldn", k);
printf("ASCII code:n");
for (int i = 0; i < k; i++)
{
ASCII = original_message[i];
printf("%d ", ASCII);
}

C 的getchar(以及getcfgetc)函数旨在读取单个字节。 它们不会直接处理"宽"或"多字节"字符,例如在 Unicode 的 UTF-8 编码中出现的字符。

但是还有其他功能是专门为处理这些扩展字符而设计的。 特别是,如果您愿意,您可以将对fgetc(fp)的调用替换为fgetwc(fp),然后您应该能够开始阅读像§这样的字符。

您必须#include <wchar.h>才能获得fgetwc原型。 您可能需要添加呼叫

setlocale(LC_CTYPE, "");

以将程序的字符集"locale"与操作系统的字符集同步。

不是你的原始代码,但我写了这个小程序:

#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main()
{
wchar_t c;
setlocale(LC_CTYPE, "");
while((c = fgetwc(stdin)) != EOF)
printf("%lc %dn", c, c);
}

当我输入"A"时,它会打印A 65. 当我输入"§"时,它会打印§ 167. 当我输入"Ƶ"时,它会打印Ƶ 437. 当我输入"†"时,它会打印† 8224.

现在,综上所述,使用fgetwc等函数读取宽字符并不是处理扩展字符的唯一方法,甚至不一定是最好的方法。 在您的情况下,它会带来许多其他后果:

  1. 您的original_message数组必须是wchar_t数组,而不是char数组。
  2. 您的original_message数组不会是普通的 C 字符串 - 它是一个"宽字符串"。 所以你不能打电话给strlen;你将不得不打电话给wcslen.
  3. 同样,您不能使用%s打印它,也不能使用%c打印其字符。 您必须记住使用%ls%lc

因此,尽管您可以将整个程序转换为在任何地方使用"宽"字符串和"w"函数,但这是一项艰巨的工作。 在许多情况下,尽管存在像您询问的那样的异常情况,但在任何地方使用 UTF-8 要容易得多,因为它往往正常工作。 特别是,只要您不必将字符串分开并使用其单个字符,或者使用strlen计算字符串的屏幕显示长度(以"字符为单位"),您就可以在任何地方使用纯 C 字符串,并让 UTF-8 序列的魔力来处理您的用户碰巧输入的任何非 ASCII 字符。

最新更新