在 c 中使用 write(2) 打印 Unicode 字符

Printing Unicode characters using write(2) in c

我正在编写一小段代码,将字符打印到屏幕上,并且必须支持 wchar_t 中包含的所有 Unicode,而我仅限于 write(2)。我设法打印了一个表情符号:

write(1, "\U0001f921", 6);

所以 \U 似乎是可行的方法。但是,我无法将 wchar_t 转换为正确的转义序列,即将 wchar_t c = L''; 转换为 \U0001f921

我什至可以在 C 中做到这一点吗?

非常感谢。

I'm working on a small piece of code that prints characters to the screen, and must support all of Unicode contained in a wchar_t, and i'm limited to only write(2).

这是一个有问题的要求组合。特别是,wchar_t 字符表示可能无法很好地使用 write() 进行输出。

更一般地说,这里有多个问题,其中:

  1. 源字符集和执行字符集的成员。
  2. 如何在源中表示执行字符集的扩展字符(通过源字符集)。
  3. 如何将执行字符集的扩展字符呈现给您选择的输出设备,以便设备按需要处理它们。

请注意,C 只指定了相当小的一组字符,必须 出现在执行字符集中。此外,其中 "extended"、字符 可能 存在,您的表情符号将属于此类。通过标准 C 接口处理扩展字符有点糊涂,因为标准为实现提供了很大的自由,让他们在那里做事。

So \U seem to be the way to go.

\U引入了“万能字名”。重要的是要了解这些序列在编译期间被转换为执行字符集的成员。

However, i can't get to convert the wchar_t into the proper escape sequence, ie converting wchar_t c = L''; into \U0001f921

假设 '' 可以直接在源字符集中表示,以便在源代码中按字面意义使用它是不安全的。这取决于您的 C 实现。通用字符名称更安全。此外,如果您想要一个宽字符常量,那么您可以尝试使用 L'\U0001f921',但是 wchar_t 很可能无法表示该字符。特别是,许多实现具有 16 位 wchar_t,并且这些实现不太可能支持您的角色作为(单个)wchar_t

使用宽字符串文字可能会更好:L"\U0001f921",但这主要对您有用,如果您正在使用特定于宽字符的函数,它将为您执行适当的编码转换. write()不会进行这样的转换,所以是否产生期望的结果取决于你的运行环境的配置。我判断您使用普通字符串文字的原始方法更有可能奏效。

如果您愿意,并且可以使用 C2011 功能,那么您还可以表达定义为以 UTF-8 编码的(常规)字符串文字,而不管实际执行字符集是什么。其形式为 u8"\U0001f921"。不过,再次强调,以这种方式产生您想要的结果取决于您的环境。 UTF-8 文字更适合与专门定义为使用 UTF-8 的接口进行交互。

Can i even do that in C ?

假设您的表情符号字符可以由类型为 wchar_t 的单个对象来表示是不安全的。可能有支持它的 C 实现,但我认为它们并不常见。

最后一点:这段代码...

write(1, "\U0001f921", 6);

... 几乎可以肯定的是,由于超出了您呈现给 write()char 数组的边界,会出现未定义的行为。我没有看到它超过 5 个字符的任何合理场景,但你写了 6,至少超过 1。如果内部表示是 UTF-8,那么该数组的长度将是 4——三个字节编码字符,一个用于字符串终止符。

您应该测量长度以找出要写入多少字节,例如:

const char *emoji = "\U0001f921";
write(1, emoji, strlen(emoji));