用C语言处理特殊字符(UTF-8编码)

用C语言处理特殊字符(UTF-8编码),c,macos,encoding,utf-8,terminal,C,Macos,Encoding,Utf 8,Terminal,我正在用C编写一个小应用程序,它读取一个简单的文本文件,然后逐行输出。问题是文本文件包含特殊字符,如Æ、Ø和Å等。当我在终端运行程序时,这些字符的输出用“?”表示 是否有一个简单的修复方法?确保没有意外丢失任何字节;一些UTF-8字符的长度超过一个字节(这是一个要点),您需要将它们全部保留下来 将缓冲区的内容打印为十六进制非常有用,因此您可以检查实际读取的字节: static void print_buffer(const char *buffer, size_t length) { siz

我正在用C编写一个小应用程序,它读取一个简单的文本文件,然后逐行输出。问题是文本文件包含特殊字符,如Æ、Ø和Å等。当我在终端运行程序时,这些字符的输出用“?”表示


是否有一个简单的修复方法?

确保没有意外丢失任何字节;一些UTF-8字符的长度超过一个字节(这是一个要点),您需要将它们全部保留下来

将缓冲区的内容打印为十六进制非常有用,因此您可以检查实际读取的字节:

static void print_buffer(const char *buffer, size_t length)
{
  size_t i;

  for(i = 0; i < length; i++)
    printf("%02x ", (unsigned int) buffer[i]);
  putchar('\n');
}
静态无效打印缓冲区(常量字符*缓冲区,大小\u t长度)
{
尺寸i;
对于(i=0;i
您可以在加载一个非常短的文件(仅包含几个字符)后执行此操作

还要确保终端设置为正确的编码,以便它将您的字符解释为UTF-8。

第一件事:

  • 读入缓冲区
  • 使用libiconv或类似工具从UTF-8获取wchar_t类型,并使用宽字符处理函数,如wprintf()
  • 使用C中的宽字符函数!大多数文件/输出处理函数都有广泛的字符变体
  • 确保您的终端能够处理UTF-8输出。拥有正确的语言环境设置和操作语言环境数据可以为您自动打开和转换许多文件。。。取决于你在做什么

    请记住UTF-8中代码点或字符的宽度是可变的。这意味着您不能只寻找一个字节,然后像ASCII一样开始读取。。。因为你可能会在代码点中间着陆。好的库在某些情况下可以做到这一点

    下面是一些代码(不是我的),演示了在C中UTF-8文件读取和宽字符处理的一些用法

    #include <stdio.h>
    #include <wchar.h>
    int main()
    {
        FILE *f = fopen("data.txt", "r, ccs=UTF-8");
        if (!f)
            return 1;
    
        for (wint_t c; (c = fgetwc(f)) != WEOF;)
            printf("%04X\n", c);
    
        fclose(f);
        return 0;
    }
    
    #包括
    #包括
    int main()
    {
    文件*f=fopen(“data.txt”,“r,ccs=UTF-8”);
    如果(!f)
    返回1;
    for(wint_t c;(c=fgetwc(f))!=WEOF;)
    printf(“%04X\n”,c);
    fclose(f);
    返回0;
    }
    
    链接


  • 可能您的文本文件是ISO-8559-1编码的,但您的终端是UTF-8。在处理面向字节的文本处理时,这种不匹配是一个标准问题;其他C程序(如标准的“cat”和“more”命令)也会做同样的事情,一般不认为这是一个错误或需要修复的东西


    如果您想在Unicode字符级别而不是字节级别上操作,这很好,但是您需要在整个程序中使用wchar作为字符类型而不是char,并为用户提供开关来指定传入文件编码的实际内容。(虽然有时可以猜测,但不太可靠。)

    我不知道这是否有帮助,但如果您确定终端和输入文件的编码相同,您可以尝试
    设置语言环境()

    #包括
    …
    setlocale(LC_CTYPE,“”);
    
    My terminal设置为UTF-8编码。程序通过fgets()将文本文件中每行的所有字符存储到一个字符数组中;如果我丢失了字节,我不知道为什么或者如何修复它。。。(刚刚开始学习C btw)@Eirik,不要使用面向ASCII的fgets()。使用我帖子中的fgetwc()。没有问题。坚持下去,C中的Unicode并不是世界上最简单的东西。。。也要熟悉这些标准:)我使用了
    setlocale(LC_CTYPE,“UTF-8”)。尽管正确配置了shell环境,但仍有必要成功读取文件。使用
    setlocale(LC_CTYPE,“”)
    ,应修改的区域设置的每个部分都是根据环境变量设置的。哦,是的,很抱歉,应该是
    ,而不是
    NULL
    #include <locale.h>
    …
    setlocale(LC_CTYPE, "");