我有与 Unicode 相关的问题,在 const char*
中打印转义的十六进制值。
- 据我了解,utf-8 包括 2、3 或 4 字节的字符,范围从井号到汉字字符。在字符串中,这些以十六进制值表示,使用\u 作为转义序列。我还了解到,在字符串中使用十六进制转义时,将包括其值可以包含在转义中的字符。例如,说“abc\x0f0dab”将包括 0f0dab,将其视为在\x 中作为十六进制,即使您只想考虑 0f0d。
现在在编写 Unicode 字符串时,假设您要编写“abc𤭢def₤ghi”,其中 𤭢 的 Unicode 为 0x24B62,₤ 为 0x00A3。所以我必须将字符串组成为“abc0x24B62def0x00A3ghi”。 0x 将考虑可以包含在其中的所有值。所以如果你想打印“abc𤭢62”,字符串将是“abc0x24B6262”。不会把整个字符串当成一个4字节的unicode(0x24B6262)值在0x之内考虑吗?如何解决这个问题?如何打印“abc𤭢62”而不是 abc(0x24B6262)?
- 我有一个字符串
const char* tmp = "abc\x0fdef";
。当我使用printf("\n string = %s", tmp);
进行打印时,它将打印 abcdef。0f
在哪里?我知道\x0f 的十进制值将存储在字符串中,即 15,所以当我们尝试打印时,应该打印 15 对吗?我的意思是,它应该是“abc15def”,但它只打印“abcdef”。
最佳答案
我认为您可能不熟悉编码的概念,因为您阅读了您的文章。
例如,您说“...₤ 的 unicode 是 0x00A3”。这是真的 - unicode 代码点 U+00A3 是井号。但是 0x00A3 不是表示井号的方式,例如 UTF-8(Unicode 的一种特定通用编码)。拿个look here明白我的意思。可以看到,U+00A3的UTF-8编码是两个字节0xc2
, 0xa3
(按顺序)。
在调用 printf()
和屏幕上出现某些内容之间会发生几件事。
首先,您的程序运行代码 printf("abc\x0fdef")
,这意味着将按顺序将以下字节写入程序的标准输出:
0x61, 0x62, 0x63, 0x0f, 0x64, 0x65, 0x66
注意:我假设您的源代码是 ASCII(或 UTF-8),这是很常见的。从技术上讲,我相信对源代码字符集的解释是实现定义的。
现在,为了查看输出,您通常会在某种 shell 中运行此程序,它最终必须将这些字节转换为可视字符。它通过使用编码来做到这一点。同样,与 ASCII 兼容的东西很常见,例如 UTF-8。在 Windows 上,CP1252 很常见。
如果是这样,您将获得以下映射:
0x61 - a
0x62 - b
0x63 - c
0x0f - the 'shift in' ASCII control code
0x64 - d
0x65 - e
0x66 - f
这将打印为“abcdef”,因为“移入”控制代码是非打印字符。
注意:以上内容可能会根据所涉及的确切字符集而变化,但除非您有特殊的设置,否则您很可能正在处理 ASCII 或 UTF-8。
如果你有一个 UTF-8 兼容的终端,下面应该打印出“abc₤def”,作为一个让你开始的例子:
printf("abc\xc2\xa3def");
有道理吗?
更新:要回答您评论中的问题:您需要区分代码点和该代码的编码的字节值代码点。
Unicode 标准定义了“代码点”,它们是字符的数值。这些通常写为 U+XYZ,其中 XYZ 是一个十六进制值。 例如,字符 U+219e 是 LEFTWARDS TWO HEADED ARROW . 这也可能写成 0x219e。你会从上下文中知道作者在谈论代码点。
当您需要对该代码点进行编码(打印或保存到文件等)时,您可以使用 UTF-8 等编码。请注意,例如,如果您使用了 UTF-32编码,每个代码点都与编码值完全对应。所以在 UTF-32 中,代码点 U+219e 确实会简单地编码为 0x219e。但是其他编码会做不同的事情。 UTF-8 会将 U+219e 编码为三个字节 0xE2 0x86 0x9E
。
最后,\x
符号只是您在 C/C++ 引用字符串中写入任意字节值的方式。如果我在 C 源代码中编写 "\xff"
,那么内存中的字符串将是两个字节 0xff 0x00
(因为它会自动获得空终止符)。
关于unicode - 如何在 C++ 的字符串中打印转义的十六进制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16756344/