FILE * f = fopen("filename", "r");
int c;
while((c = fgetc(f)) != EOF) {
printf("%c\n", c);
}
您好,我已经搜索了整整一个小时,找到了许多关于 Unicode 的明智论文,但没有回答这个简单的问题:
在使用 gcc 和 bash 的 Linux 上,可以管理 UTF8 的这四行的最短等效项是什么。
谢谢
FILE * f = fopen("filename", "r");
int c;
while((c = fgetc(f)) != EOF) {
printf("%c\n", c);
}
您好,我已经搜索了整整一个小时,找到了许多关于 Unicode 的明智论文,但没有回答这个简单的问题:
在使用 gcc 和 bash 的 Linux 上,可以管理 UTF8 的这四行的最短等效项是什么。
谢谢
考虑到您的系统,这样的事情应该可以工作:
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main() {
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE * f = fopen("filename", "r");
wint_t c;
while((c = fgetwc(f)) != WEOF) {
wprintf(L"%lc\n", c);
}
}
您的原始代码的问题在于 C 没有意识到(或关心)字符是多字节的,因此您的多字节字符将被\n
每个字节之间的字符破坏。在此版本中,一个字符被视为 UTF-8,因此%lc
现在可以表示多达 6 个实际字节,这些字节可以保证正确输出。如果输入有任何 ASCII,它将像以前一样简单地每个字符使用一个字节(因为 ASCII 与 UTF-8 兼容)。
strace
对于调试这样的事情总是有用的。例如,如果文件仅包含££
(£ 具有 UTF-8 序列 \302\243)。您的版本产生:
write(1, "\302\n\243\n\302\n\243\n\n\n", 10) = 10
而我的,
write(1, "\302\243\n\302\243\n", 6) = 6
请注意,一旦您读取或写入流(包括stdout
),它将被设置为字节或宽方向,如果您想更改它,您需要重新打开流。因此,例如,如果您想读取 UTF-8 文件,但保持stdout
面向字节,则可以将其替换为wprintf
:
printf("%lc\n", c);
这涉及后台的额外代码(以转换格式),但与其他需要字节流的代码提供更好的兼容性。