Вывести wchar на консоль Linux? - PullRequest
       82

Вывести wchar на консоль Linux?

8 голосов
/ 08 октября 2011

Моя программа на C вставлена ​​ниже.В bash программа печатает "char is", Ω не печатается.Все мои локали en_US.utf8.

#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>

int main() {
   int r;
   wchar_t myChar1 = L'Ω';
   r = wprintf(L"char is %c\n", myChar1);
}

Ответы [ 3 ]

12 голосов
/ 08 октября 2011

Это было довольно интересно.По-видимому, компилятор переводит омегу из UTF-8 в UNICODE, но каким-то образом libc все испортил.

Прежде всего: спецификатор формата %c ожидает char (даже в wprintf -version), поэтому вы должны указать %lc (и, следовательно, %ls для строк).

Во-вторых, если вы запускаете свой код таким образом, языковой стандарт устанавливается на C (он не берется автоматически из среды).Вы должны вызвать setlocale с пустой строкой, чтобы взять локаль из окружения, чтобы libc снова был счастлив.

#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <locale.h>

int main() {
    int r;
    wchar_t myChar1 = L'Ω';
    setlocale(LC_CTYPE, "");
    r = wprintf(L"char is %lc (%x)\n", myChar1, myChar1);
}
6 голосов
/ 08 октября 2011

Вместо ответа, предлагающего исправить LIBC, вы можете сделать это:

#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>

// NOTE: *NOT* thread safe, not re-entrant
const char* unicode_to_utf8(wchar_t c)
{
    static unsigned char b_static[5];
    unsigned char* b = b_static; 

    if (c<(1<<7))// 7 bit Unicode encoded as plain ascii
    {
        *b++ = (unsigned char)(c);
    }
    else if (c<(1<<11))// 11 bit Unicode encoded in 2 UTF-8 bytes
    {
        *b++ = (unsigned char)((c>>6)|0xC0);
        *b++ = (unsigned char)((c&0x3F)|0x80);
    }
    else if (c<(1<<16))// 16 bit Unicode encoded in 3 UTF-8 bytes
        {
        *b++ = (unsigned char)(((c>>12))|0xE0);
        *b++ =  (unsigned char)(((c>>6)&0x3F)|0x80);
        *b++ =  (unsigned char)((c&0x3F)|0x80);
    }

    else if (c<(1<<21))// 21 bit Unicode encoded in 4 UTF-8 bytes
    {
        *b++ = (unsigned char)(((c>>18))|0xF0);
        *b++ = (unsigned char)(((c>>12)&0x3F)|0x80);
        *b++ = (unsigned char)(((c>>6)&0x3F)|0x80);
        *b++ = (unsigned char)((c&0x3F)|0x80);
    }
    *b = '\0';
    return b_static;
}


int main() {
    int r;
    wchar_t myChar1 = L'Ω';
    r = printf("char is %s\n", unicode_to_utf8(myChar1));
    return 0;
}
4 голосов
/ 08 октября 2011

Используйте {glib, libiconv, ICU} для преобразования его в UTF-8 перед выводом.

...