【问题标题】:Print Unicode characters by code按代码打印 Unicode 字符
【发布时间】:2015-03-05 14:49:06
【问题描述】:

我有一个uint32_t 数组。每个都是代表 Unicode 字符的值。我想像字符串一样打印数组,但我无法让它工作。

我尝试了很多不同的东西

typedef struct String {
    uint32_t *characters;
    unsigned long length;
} WRString;

char* WRStringToString(WRString *wstr){
    char *string = malloc(sizeof(char) * wstr->length * 4);
    int i = 0;
    int j = 0;
    for (; i < wstr->length; i++) {
        string[j++] = wstr->characters[i];

        char byte2 = (char)wstr->characters[i] >> 8;
        if (byte2) {
            string[j++] = byte2;

            char byte3 = (char)wstr->characters[i] >> 16;
            if (byte3) {
                string[j++] = byte3;

                char byte4 = (char)wstr->characters[i] >> 24;
                if (byte4) {
                    string[j++] = byte4;
                }
            }
        }
    }
    return string;
}

永远在一起

WRString *string; //Characters are 0xD6, 0x73, 0x74, 0x65, 0x72, 0x72, 0x65, 0x69, 0x63, 0x68     

我试过了:

setlocale(LC_CTYPE,"de_DE.UTF-8");
puts(WRStringToString(string));

\326\377\377\377sterreich

wprintf(L"%s",WRStringToString(string));

只要没有设置本地,就给出相同的结果。

Printing UTF-8 strings with printf - wide vs. multibyte string literalsPrinting Unicode Character (stored in variables) in C 并没有真正帮助我。

有什么建议吗?

【问题讨论】:

  • 那些不是字符串中的 UTF-8 字符,或者您可以直接打印它们。它们是 Unicode 代码点。请保持您的术语直截了当。
  • @MarkRansom,不,他的uint32_t中似乎只有utf8字节编码
  • 问题中有很多术语问题,不清楚您在问什么。我不知道这只是语言问题,还是对 UTF-8、字符等 Unicode 概念有误解。
  • @JensGustedt 不,他的示例中的第一个字符是 0xD6,它是 Ö 的代码点。我怀疑这是一个合法的 UTF-8 序列。
  • @MarkRansom,好的,是的,所以他真的很困惑。

标签: c unicode utf-8


【解决方案1】:

这些似乎只是 unicode 代码点。将它们一一存储在wchar_t 字符串中,然后使用

printf("%ls\n", wstring);

您必须在程序开始时将语言环境设置为系统的默认设置:

set_locale(LC_ALL, "");

【讨论】:

  • 根据this wchar_t 可以小到一个字节。所以看起来并不完美。
  • 我看不到任何正在运行的东西 wchar_t l[11] = {0x1F330, 0xD6, 0x73, 0x74, 0x65, 0x72, 0x72, 0x65, 0x69, 0x63, 0x68}; printf("%ls\n", l); 我又混合了一些东西吗?
  • 您是否将语言环境设置为 utf8? C(默认)语言环境不会处理这些字符。
  • 您也忘记了字符串末尾的0 字符。如果您使用正确的语言环境,另一种方法是使用普通字符串 char s[] = "Östereich" 应该可以开箱即用。
  • @JensGustedt:很少见,但并非不可能。特别是 SMP 平面 (U+10000 –​U+1FFFF) 包含一些有用的代码点,如音乐和数学符号以及表情符号(在聊天/IM 系统中越来越受欢迎)。显然,如果不使用 UTF-16 代理,那些不适合 16 位。
【解决方案2】:

Jens Gustedt 的回答指出了正确的方向,但我继续使用 uint32_t,因为我需要支持 Unicode 的 Emoji,而 wchar_t 对于这些表情来说可能太小了。 (如 Remy Lebeau 所说)

这似乎工作得很好:

setlocale(LC_CTYPE,"de_DE.UTF-8");
printf("%ls\n", string->characters);

【讨论】:

  • 不,只是看起来如此。在 wchar_t 只有 16 位的情况下,这将在你的脚下爆炸。具有 16 位 wchar_t 的平台根本无法处理 Emoji 和类似的东西。
  • @JensGustedt 是的,我知道这一点。但我会坚持使用uint32_t,因为项目中使用的许多其他代码已经在使用uint32_t。即使在我无法使用上述方法打印的系统上,我至少能够进行我需要做的其他比较。 (表情符号的 unicode 代码点非常很重要)
  • 但是一定要在 16 位 wchar_t 的机器上构建一些禁止编译的东西。只是将错误的指针类型传递给printf 就是一个定时炸弹。
  • @JensGustedt 感谢您的建议。我打算做这样的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-22
  • 1970-01-01
  • 2013-06-01
  • 1970-01-01
相关资源
最近更新 更多