C语言 无法输入UTF-8字符,即使我已将终端的字符编码切换为UTF-8

q3aa0525  于 2023-08-03  发布在  其他
关注(0)|答案(3)|浏览(153)

我已经使用intl.cpl将终端编码更改为UTF-8,并将系统区域设置更改为UTF-8。但是,我仍然无法输入UTF-8字符,例如å。如果我输入chcp,则输出为:

Active code page: 65001

字符串
这表明UTF-8是“激活的”。
那么,为什么这段代码不起作用:

#include <stdio.h>

int main(void) {
    char myChar;

    printf("Enter the letter å: ");
    scanf("%c", &myChar);
    printf("Entered letter: %c", myChar);

    return 0;
}


输入为å
输出为:

Enter the letter å: å
Entered letter:


为什么会发生这种情况?这真的很令人沮丧,我真的很感激一些帮助。- 谢谢-谢谢

vsikbqxv

vsikbqxv1#

C程序的默认区域设置是C。将区域设置切换到您设置的用户区域设置。
UTF-8中的å需要 * 两个 * 字节。它不适合一个char。使用宽字符。

#include <stdio.h>
#include <locale.h>
#include <wchar.h>
int main(void) {
    setlocale(LC_ALL, "");
    wchar_t myChar;
    printf("Enter the letter å: ");
    scanf("%lc", &myChar);
    printf("Entered letter: %lc", myChar);
}

字符串

3bygqnnd

3bygqnnd2#

为什么会发生这种情况?
因为在UTF-8中,å被编码为多字节序列。您只阅读和回显第一个字节。多字节字符不能存储在单个char中,也不能由单个char表示.这差不多就是“多字节”的定义。
这里的一个关键问题是一些不匹配的术语。在大多数情况下,C语言规范和标准库文档使用术语“字符”,非限定的,他们意味着一个char大小的二进制数。也就是说,粗略地说,一个字节。
但是,Unicode规范中的“字符”是非限定的,它们通常是指 * 抽象 * 字符。你不能在这个意义上触摸人物。你可以触摸到的是Unicode所称的 * 编码字符 *,它通过 * 代码单元 * 的序列根据特定的 * 编码形式 * 表示抽象字符的Unicode * 字符代码 *。UTF-8是一种Unicode编码形式,具有由8位代码单元组成的可变长度代码序列。
当你说你想输入一个“Unicode字符”时,你的意思似乎是你想输入一个完整的代码序列,对于UTF-8,它可能是从一个到四个字节的任何地方(而对于UTF-16,它可能是一个或两个16位单位)。在C中,最透明的方法是输入到C字符串中,并从C字符串中输出。举例来说:

#include <stdio.h>

int main(void) {
    char mb_char[5];

    printf("Enter the letter å: ");
    scanf("%4s", &mb_char);
    printf("Entered letter: %s", mb_char);

    return 0;
}

字符串
但是,请注意,尽管这肯定会读取至少一个UTF-8编码的字符,但如果用户输入多个字符,它可能会读取多个字符(但可能少于两个)。
总的来说,如果您可以忽略特定的编码形式(但假设它使用一个字节的代码单元),那么将其全部视为字符串是一个很好的策略。如果您只需要读取、存储和回显提供给程序的字符数据,则会出现这种情况。
另一方面,如果您需要执行任何编码感知的操作,或者希望更干净地处理具有不同大小代码单元的编码,或者执行其他各种Unicode感知的活动,则可能应该使用专门用于处理这些操作的库。例如,ICU是一个受欢迎且得到很好支持的版本,我个人在使用它时取得了很大的成功。

kuarbcqp

kuarbcqp3#

这是不可能的爱或金钱读取UTF-8字符从Windows终端使用Microsoft C运行时库又名msvcrt。你试图做错了,这在其他答案中有详细说明,但即使你做对了,也就是说。以在所有其他系统上都能工作的方式,它仍然不能在使用msvcrt的Windows上工作。
您的选项包括:

相关问题