我正在尝试从文本文件中读取不可打印的字符,打印出字符的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
(以及getc
和fgetc
)函数旨在读取单个字节。 它们不会直接处理"宽"或"多字节"字符,例如在 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
等函数读取宽字符并不是处理扩展字符的唯一方法,甚至不一定是最好的方法。 在您的情况下,它会带来许多其他后果:
- 您的
original_message
数组必须是wchar_t
数组,而不是char
数组。 - 您的
original_message
数组不会是普通的 C 字符串 - 它是一个"宽字符串"。 所以你不能打电话给strlen
;你将不得不打电话给wcslen
. - 同样,您不能使用
%s
打印它,也不能使用%c
打印其字符。 您必须记住使用%ls
或%lc
。
因此,尽管您可以将整个程序转换为在任何地方使用"宽"字符串和"w
"函数,但这是一项艰巨的工作。 在许多情况下,尽管存在像您询问的那样的异常情况,但在任何地方使用 UTF-8 要容易得多,因为它往往正常工作。 特别是,只要您不必将字符串分开并使用其单个字符,或者使用strlen
计算字符串的屏幕显示长度(以"字符为单位"),您就可以在任何地方使用纯 C 字符串,并让 UTF-8 序列的魔力来处理您的用户碰巧输入的任何非 ASCII 字符。