Как обрабатывать char16_t или char32_t с printf и scanf на C?
Если я напишу:
char a = 'A';
printf("%x %c", a, a);
он выдаст на выходе «41 А». Аналогично, когда я пишу
char32_t c = U'🍌';
printf("%x %c", c, c); //even tried %lc and %llc
он выдаст на выходе «1f34c L» вместо ожидаемого «1f34c 🍌»!
Здесь что-то не так? Как я могу напечатать символы char16_t и char32_t на stdout?
Кроме того, какой описатель формата я должен использовать для получения ввода char16_t / char32_t от scanf?
char32_t c;
scanf("%c", &c); //🍌
printf("%x %c", c, c);
это даст результат "f0 ".
2 ответа
и ничего особенного. Они действительно просто
uint_least16_t
а также
uint_least32_t
. У них нет такой большой поддержки. Единственное, для чего они используются, в основном
u
а также
U
литералы. Они могут быть не UTF-16 и не UTF-32 - проверьте
__STDC_UTF_16__
а также
__STDC_UTF_32__
макросы, прежде чем предположить, что они есть. Только самые основные функции преобразования входят в стандартную комплектацию. В стандарте есть только функции конвертации или в многобайтовую кодировку и обратно. Чтобы сделать с ними что- то еще, вы должны реализовать это самостоятельно.
Язык C действительно имеет две кодировки - многобайтовое представление символов, зависящее от локали , и широкое представление символов.
Что-то здесь не так?
Символ, который вы набрали в исходном файле , интерпретируется компилятором как значение, специфичное для конкретной реализации. Gcc сделает
UTF-8, то препроцессор gcc сдвинет значения влево, поэтому
''
равно
(int)0xF09F8D8C
на gcc — поведение многосимвольных литералов
'something'
определяется реализацией. Затем значение этого символа присваивается . Это вовсе не значение UTF-32.
Как я могу вывести символы char16_t и char32_t на стандартный вывод?
Преобразуйте их в многобайтовую строку. Затем просто распечатайте его с помощью
%s
.
#include <stdlib.h>
#include <uchar.h>
#include <stdio.h>
#include <wchar.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, "en_US.UTF-8");
char32_t c = U'';
char buf[MB_LEN_MAX + 1] = {0};
mbstate_t ps;
memset(&ps, 0, sizeof(ps));
c32rtomb(buf, c, &ps);
printf("%s\n", buf);
}
Печать данных зависит от локали , так как печать выполняется в локали, указанной пользователем. Локаль по умолчанию
C
и не имеет поддержки UTF. Итак, сначала вам нужно установить локаль на что-то совместимое с utf. Тогда позвони
c32rtomb
. Обратите внимание, что поток выбирает кодировку при первой печати в
glibc
- обязательно позвоните
setlocale
прежде чем делать что-либо с потоком, с которым вы хотите работать.
какой спецификатор формата я должен использовать для получения ввода char16_t / char32_t из scanf?
Нет, нет. Вы должны использовать
wchar_t
или простой
char
строки для чтения символов от пользователя в кодировке, указанной в его локали. Затем вы можете конвертировать в/из
char16_t
а также
char32_t
Если хочешь. Если вы хотите специально читать символы UTF-32, вам нужно написать это самостоятельно, чтобы убедиться, что ваш код читает
UTF-32
персонажи. Я рекомендую либунистринг.
я дал значение в
HEX
формат
symbol = 0x0001F34C
есть и другие способы решить эту проблему, вот как я знаю, проверьте следующий код в c, мы не можем напечатать символ, используя
%c
или просто
printf
вот объясните, зачем использовать wchar_t вместо char
char
имеют кодировку UTF-8, а wchar_t имеют UTF-32, что увеличивает его диапазон
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main() {
setlocale(LC_CTYPE, "");
wchar_t symbol = 0x0001F34C;
wprintf(L"%x %lc\n",symbol,symbol);
}
output: 1f34c
проверьте следующую ссылку Печать символа Unicode в C , UNICODE банана emoji , char32_t