如何在 C 中使用 printf 和 scanf 处理 char16_t 或 char32_t?
How to handle char16_t or char32_t with printf and scanf in C?
如果我写:
char a = 'A';
printf("%x %c", a, a);
它将产生输出“41 A”。
类似地当我写
char32_t c = U'';
printf("%x %c", c, c); //even tried %lc and %llc
它将产生输出“1f34c L”而不是预期的“1f34c”!
这里有什么问题吗?如何将 char16_t 和 char32_t 字符打印到标准输出?
此外,我应该使用哪种格式说明符从 scanf 获取 char16_t / char32_t 输入?
char32_t c;
scanf("%c", &c); //
printf("%x %c", c, c);
这将产生输出“f0 �”。
我已经以 HEX
格式给出了值 symbol = 0x0001F34C
还有其他方法可以解决这个问题,这就是我如何知道检查以下 c 中的代码我们不能使用 %c
或打印符号只有 printf
here is explain why to use wchar_t instead of 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
检查以下 link
, UNICODE of emoji banana , char32_t
char16_t
和 char32_t
没什么特别的。它们实际上只是 uint_least16_t
和 uint_least32_t
。他们没有那么大的支持。它们唯一用于基本上 u
和 U
文字。它们可能 不是 是 UTF-16 和 UTF-32 - 在假设它们是之前检查 __STDC_UTF_16__
和 __STDC_UTF_32__
宏。只有非常基本的转换功能是标准的。在标准中,只有将 char16_t
或 char32_t
转换为多字节编码并返回的函数。要用它们做更多任何事情,您必须自己实施。
C 语言实际上有两种编码方式 - locale dependent 多字节字符表示和宽字符表示。
Is there something wrong here?
您在源文件中键入的 ''
字符 被编译器解释为某个特定于实现的值。 Gcc 将使 </code> 成为 UTF-8,然后 <a href="https://gcc.gnu.org/onlinedocs/cpp/Implementation-defined-behavior.html#Implementation-defined-behavior" rel="nofollow noreferrer">gcc preprocessor</a> 会将值左移,因此 <code>''
等于 (int)0xF09F8D8C
on gcc - 多字符文字的行为 'something'
是实现定义的。然后将该字符的值赋给char32_t
。这根本不是 UTF-32 值。
How can I print char16_t and char32_t characters onto stdout?
将它们转换为多字节字符串。然后用 %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);
}
打印数据依赖于 locale,因为打印是在用户指定的语言环境中完成的。默认语言环境是 C
并且不支持 UTF。所以首先你必须将你的语言环境设置为与 utf 兼容的东西。然后调用c32rtomb
。请注意,流在 glibc
中首次打印时选择编码 - 确保在 对要使用的流进行任何操作之前调用 setlocale
。
which format specifier should I use to get char16_t / char32_t input from scanf?
None,还有none。您应该使用 wchar_t
或纯 char
字符串以用户在其语言环境中指定的编码读取字符。然后你可以根据需要转换 to/from char16_t
和 char32_t
。如果你想专门读取 UTF-32 字符,那么你必须自己编写它以确保你的代码读取 UTF-32
个字符。我推荐 libunistring.
如果我写:
char a = 'A';
printf("%x %c", a, a);
它将产生输出“41 A”。 类似地当我写
char32_t c = U'';
printf("%x %c", c, c); //even tried %lc and %llc
它将产生输出“1f34c L”而不是预期的“1f34c”!
这里有什么问题吗?如何将 char16_t 和 char32_t 字符打印到标准输出?
此外,我应该使用哪种格式说明符从 scanf 获取 char16_t / char32_t 输入?
char32_t c;
scanf("%c", &c); //
printf("%x %c", c, c);
这将产生输出“f0 �”。
我已经以 HEX
格式给出了值 symbol = 0x0001F34C
还有其他方法可以解决这个问题,这就是我如何知道检查以下 c 中的代码我们不能使用 %c
或打印符号只有 printf
here is explain why to use wchar_t instead of 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
检查以下 link
char16_t
和 char32_t
没什么特别的。它们实际上只是 uint_least16_t
和 uint_least32_t
。他们没有那么大的支持。它们唯一用于基本上 u
和 U
文字。它们可能 不是 是 UTF-16 和 UTF-32 - 在假设它们是之前检查 __STDC_UTF_16__
和 __STDC_UTF_32__
宏。只有非常基本的转换功能是标准的。在标准中,只有将 char16_t
或 char32_t
转换为多字节编码并返回的函数。要用它们做更多任何事情,您必须自己实施。
C 语言实际上有两种编码方式 - locale dependent 多字节字符表示和宽字符表示。
Is there something wrong here?
您在源文件中键入的 ''
字符 被编译器解释为某个特定于实现的值。 Gcc 将使 </code> 成为 UTF-8,然后 <a href="https://gcc.gnu.org/onlinedocs/cpp/Implementation-defined-behavior.html#Implementation-defined-behavior" rel="nofollow noreferrer">gcc preprocessor</a> 会将值左移,因此 <code>''
等于 (int)0xF09F8D8C
on gcc - 多字符文字的行为 'something'
是实现定义的。然后将该字符的值赋给char32_t
。这根本不是 UTF-32 值。
How can I print char16_t and char32_t characters onto stdout?
将它们转换为多字节字符串。然后用 %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);
}
打印数据依赖于 locale,因为打印是在用户指定的语言环境中完成的。默认语言环境是 C
并且不支持 UTF。所以首先你必须将你的语言环境设置为与 utf 兼容的东西。然后调用c32rtomb
。请注意,流在 glibc
中首次打印时选择编码 - 确保在 对要使用的流进行任何操作之前调用 setlocale
。
which format specifier should I use to get char16_t / char32_t input from scanf?
None,还有none。您应该使用 wchar_t
或纯 char
字符串以用户在其语言环境中指定的编码读取字符。然后你可以根据需要转换 to/from char16_t
和 char32_t
。如果你想专门读取 UTF-32 字符,那么你必须自己编写它以确保你的代码读取 UTF-32
个字符。我推荐 libunistring.