【问题标题】:How to print escaped hexadecimal in a string in C++?如何在 C++ 中的字符串中打印转义的十六进制?
【发布时间】:2013-05-21 07:36:02
【问题描述】:

我有关于 Unicode 的问题,在 const char* 中打印转义的十六进制值。

  1. 据我了解,utf-8 包括 2、3 或 4 字节字符,范围从磅符号到汉字字符。在字符串中,这些以十六进制值表示,使用 \u 作为转义序列。我也明白,在字符串中使用十六进制转义时,将包含其值可以包含在转义中的字符。例如说“abc\x0f0dab”将包含 0f0dab 以在 \x 中被视为十六进制,即使您只想考虑 0f0d。

现在在编写 Unicode 字符串时,假设您要编写“abc????def₤ghi”,其中 Unicode 表示 ????是 0x24B62,₤ 是 0x00A3。所以我必须将字符串组合为“abc0x24B62def0x00A3ghi”。 0x 将考虑可以包含在其中的所有值。因此,如果您想打印“abc????62”,则字符串将为“abc0x24B6262”。整个字符串不会被视为 0x 内的 4 字节 unicode (0x24B6262) 值吗?如何解决这个问题?如何打印“abc????62”而不是abc(0x24B6262)?

  1. 我有一个字符串const char* tmp = "abc\x0fdef";。当我使用printf("\n string = %s", tmp); 打印时,它将打印 abcdef。 0f 在哪里?我知道 \x0f 的十进制值将存储在字符串中,即 15,所以当我们尝试打印时,应该打印 15 对吗?我的意思是,它应该是“abc15def”,但它只打印“abcdef”。

【问题讨论】:

  • "...它将打印 abcdef。"你的 C 编译器没有遵循规范。
  • "unicode of... ₤ 是 0x00A3" -- 不是 POUND SIGN 它是 LIRA SIGN U+20A4

标签: unicode hex


【解决方案1】:

看了你的帖子,我想你可能对编码的概念不熟悉。

例如,您说“... ₤ 的 unicode 是 0x00A3”。这是真的 - unicode 代码点 U+00A3 是井号。但是 0x00A3 不是您表示井号的方式,例如 UTF-8(Unicode 的一种特殊常见编码)。采取look here 看看我的意思。可以看到,U+00A3的UTF-8编码是两个字节分别是0xc20xa3(依次)。

在您致电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");

有意义吗?


更新:要回答您评论中的问题:您需要区分 codepointencoding 的字节值代码点。

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(因为它会自动获得一个空终止符)。

【讨论】:

  • 哇真棒解释!!!你是对的。我可能应该启用 utf-8 编码。也请您尝试回答我的第二个问题。 '\x' 和 '0x' 和 'U+' 有什么区别???
  • @VISHWAASMANJUNATH:我在答案的末尾添加了更多信息,希望能解决这个问题。
  • 太好了,我终于明白了很多。没有多少人对编码非常了解。总结一下:
  • U+XYZ 只是一个定义为表示 unicode 的值,但是在将其存储在内存中时,每种编码都有不同的方式,UTF-8 将其存储为 0xA 0xB 0xC 假设 A、B 和 C 相等到一个字节。 \x 用于将值(十六进制值)按原样写入内存,以便编译器不会将其误认为是字符并将其转换为它的 ascii。 \x 0x 是 U+ 可以互换吗? unicode U+219e 的含义可以表示为 0x219e 和 \x219e 并且在字符串中使用时可以将 0xE2 0x86 0x9E 写为 \xE2 \x86 \x9E。(我确定你不能将其写为 U+E2 U+86 U+9E)
  • @VISHWAASMANJUNATH:通常,\x、0x 或 U+ 的选择取决于上下文。它们并不总是可以互换的。在 C 字符串中,只有 \x 有意义(也有 \u,但这是另一回事)。在字符串之外但仍在 C 源代码中,0x 有意义。只是在对话中谈论 unicode,我见过用 U+0x 编写的代码点,但几乎从未见过 \x
猜你喜欢
  • 2011-12-25
  • 2016-12-22
  • 1970-01-01
  • 2023-03-18
  • 2014-10-07
  • 2019-07-27
  • 1970-01-01
  • 2015-01-06
  • 2012-03-25
相关资源
最近更新 更多