【问题标题】:Printing universal characters打印通用字符
【发布时间】:2011-10-28 05:23:00
【问题描述】:

谁能解释为什么通用字符文字(例如“\u00b1”)被编码为 UTF-8 字符字符串?为什么下面会打印加号/减号?

#include <iostream>
#include <cstring>
int main()
{
  std::cout << "\u00b1" << std::endl;
  return 0;
}

这与我当前的语言环境有关吗?

【问题讨论】:

    标签: c++


    【解决方案1】:

    2.13.2。 [...]

    5/ 通用字符名被转换为编码,在 命名字符的执行字符集。如果没有 这样的编码,universal-character-name 被翻译成 实现定义的编码。 [注意:在翻译阶段 1,a 每当实际扩展时,都会引入通用字符名称 在源文本中遇到字符。因此,所有扩展 字符是根据通用字符名称来描述的。 但是,实际的编译器实现可能会使用自己的原生 字符集,只要得到相同的结果。 ]

    2.2。 [...] 执行字符集成员的值 是实现定义的,任何其他成员都是 特定于语言环境。

    简而言之,您的问题的答案在您的编译器文档中。然而:

    2.2。 2/由universal-character-name指定的字符 \UNNNNNNNN 是 ISO/IEC 中字符短名称的字符 10646 是 NNNNNNNN;指定的字符 通用字符名称 \uNNNN 是其字符的那个字符 ISO/IEC 10646 中的简称为 0000NNNN。如果十六进制值为 通用字符名称小于 0x20 或在 0x7F-0x9F 范围内 (含),或者如果通用字符名称指定一个字符 在基本源字符集中,则程序格式错误。

    所以您可以保证您命名的字符被翻译成实现定义的编码,可能是特定于语言环境的。

    【讨论】:

    • 谢谢。我现在在 GNU 文档中看到执行字符集是由 -fexec-charset 设置的,默认是 UTF-8。
    【解决方案2】:

    \u00b1± 符号,因为无论语言环境如何,它都是正确的 unicode 表示。

    您的代码在ideone, see here

    【讨论】:

      【解决方案3】:

      字符串字面量,例如"abcdef" 是简单的字节数组(const char[] 类型)。编译器将其中的非 ASCII 字符编码为实现定义的内容。谣言说 Visual C++ 使用当前 Windows 的 ANSI 代码页,而 GCC 使用 UTF-8,所以你可能使用 GCC :)

      因此,\uABCD 在编译时由编译器解释并转换为该编码中的相应值。 IE。它可以将一个或多个字节放入字节数组中:

      sizeof("\uFE58z") == 3 // visual C++ 2010
      sizeof("\uFE58z") == 5 // gcc 4.4 mingw
      

      然而,cout 将如何打印字节数组,取决于区域设置。您可以通过std::ios_base::imbue() 调用更改流的区域设置。

      【讨论】:

      • 为什么有z? (诚​​实的问题)
      【解决方案4】:

      C++ 字符集

      随着 C++ 的标准化,回顾语言中包含的一些用于处理字符集的机制是很有用的。这似乎是一个非常简单的问题,但需要解决一些复杂问题。

      首先要考虑的是 C++ 中“基本源字符集”的概念。这被定义为:

          all ASCII printing characters 041 - 0177, save for @ $ ` DEL
      
          space
      
          horizontal tab
      
          vertical tab
      
          form feed
      
          newline
      

      或总共 96 个字符。这些是用于组成 C++ 源程序的字符。

      一些国家字符集,例如欧洲 ISO-646 之一,将其中一些字符位置用于其他字母。受影响的 ASCII 字符是:

          [ ] { } | \
      

      为了解决这个问题,C++ 定义了可用于表示这些字符的三字符序列:

          [       ??(
      
          ]       ??)
      
          {       ??<
      
          }       ??>
      
          |       ??!
      
          \       ??/
      
          #       ??=
      
          ^       ??'
      
          ~       ??-
      

      三字母序列在编译过程的早期就被映射到相应的基本源字符。

      C++ 还具有“替代标记”的概念,可用于将标记替换为其他标记。代币及其替代品的列表如下:

          {       <%
      
          }       %>
      
          [       <:
      
          ]       :>
      
          #       %:
      
          ##      %:%:
      
          &&      and
      
          |       bitor
      
          ||      or
      
          ^       xor
      
          ~       compl
      
          &       bitand
      
          &=      and_eq
      
          |=      or_eq
      
          ^=      xor_eq
      
          !       not
      
          !=      not_eq
      

      另一个想法是“基本执行字符集”。这包括所有基本的源字符集,以及用于警报、退格、回车和 null 的控制字符。 “执行字符集”是基本执行字符集加上附加的实现定义字符。这个想法是源字符集用于定义 C++ 程序本身,而执行字符集用于 C++ 应用程序执行时。

      鉴于此概念,可以在正在运行的程序中操作其他字符,例如来自西里尔文或希腊文的字符。字符常量可以使用以下任何一种来表示:

          \137            octal
      
          \xabcd          hexadecimal
      
          \u12345678      universal character name (ISO/IEC 10646)
      
          \u1234          -> \u00001234
      

      此表示法使用源字符集来定义执行集字符。通用字符名称可用于标识符(如果是字母)和字符文字中:

          '\u1234'
      
          L'\u2345'
      

      您的本地 C++ 编译器中可能尚不存在上述功能。在开发国际化应用程序时,它们是重要的考虑因素。

      【讨论】:

      • 你的大部分回答与问题无关,充其量只是分散注意力。
      • @Konrad Rudolph 是一个完全支持的分析器
      • 其实答案是正确的。但它是有用的方式。
      • 你只是从一些书籍或教程中复制/粘贴,你抄袭的前3/4与这个问题无关。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-25
      • 1970-01-01
      • 1970-01-01
      • 2018-06-22
      • 2016-12-25
      相关资源
      最近更新 更多