流出扩展 ASCII
Streaming Out Extended ASCII
我知道只有正字符 ASCII 值才能保证跨平台支持。
在Visual Studio2015年,我能做到:
cout << '\xBA';
并打印:
║
当我在 http://ideone.com 上尝试时,我没有打印任何东西。
如果我尝试使用文字字符直接打印:
cout << '║';
Visual Studio 发出警告:
warning C4566: character represented by universal-character-name '\u2551' cannot be represented in the current code page (1252)
然后打印:
?
当此命令在 http://ideone.com 上 运行 时,我得到:
14849425
我读到 wchar
s 可能为此提供跨平台方法。真的吗?或者我只是在扩展 ASCII 上运气不好?
这里有两个不同的概念。
第一个是语言环境之一,在Microsoft-ese中通常称为"code page"。语言环境定义了哪些视觉字符由哪个字节序列表示。在您的第一个示例中,无论您的程序以何种语言环境执行,它都会显示“║”字符,以响应字节 0xBA。
其他语言环境或代码页将针对相同的字节显示不同的字符。许多语言环境是多字节语言环境,其中可能需要几个字节才能显示单个字符。例如在UTF-8语言环境中,同一个字符║需要三个字节来显示:0xE2 0x95 0x91.
这里的第二个概念是源代码字符集之一,它来自编译源代码之前编辑的语言环境。当您在源代码中输入 ║ 字符时,如果您的编辑器使用 UTF-8 语言环境,它可能会被表示为 0xBA 字符,或者可能是 0xE2 0x95 0x91 序列。编译器在读取源代码时,只会看到实际的字节序列。一切都减少到字节。
幸运的是,所有的C++关键字都使用US-ASCII,所以用什么字符集来编写C++代码并不重要。直到你开始使用非拉丁字符。这会导致编译器警告,基本上是通知您,您使用的东西可能有效,也可能无效,具体取决于结果程序运行的最终语言环境。
首先,您的输入源文件有自己的编码。您的编译器需要能够读取此编码(可能需要 flags/settings 的帮助)。
对于一个简单的字符串,编译器可以自由地做它想做的事,但它必须产生一个 const char[]
。通常,编译器会尽可能保留源编码,因此程序中存储的字符串将具有输入文件的编码。在某些情况下,编译器会进行转换,例如,如果您的文件是 UTF-16(您不能在 char
s 中放入 UTF-16 字符)。
当你使用 '\xBA' 时,你写了一个原始字符,你自己选择了你的编码,所以没有来自编译器的编码。
当你使用'║'
时,'║'
的类型不一定是char
。如果字符在编译器字符集中不能表示为单个字节,则其类型将为 int
。在 Visual Studio 与 Windows-1252 源文件的情况下,'║'
不适合,因此它将是 int
类型并由 [=18 这样打印=].
您可以在字符串文字上强制使用前缀编码。 u8""
将强制使用 UTF-8,u""
UTF-16 和 U""
UTF-32。请注意,L""
前缀会给你一个宽字符 wchar_t
字符串,但它仍然依赖于实现。 Windows 上的宽字符是 UCS-2(每个字符 2 个字节),但 linux.
上是 UTF-32(每个字符 4 个字节)
打印到控制台只取决于变量的类型。 cout <<
重载了所有常见类型,因此它的作用取决于类型。 cout <<
通常会将 char
字符串按原样提供给控制台(实际上是标准输入),而 wcout <<
通常会按原样提供 wchar_t
字符串。其他组合可能有转换或解释(比如输入 int
)。 UTF-8 字符串是 char
字符串,因此 cout <<
应该始终正确地提供它们。
接下来是控制台本身。控制台是一个完全独立的软件。你给它一些字节,它显示它们。 它一点也不关心你的程序。它使用自己的编码,并尝试使用此编码打印您输入的字节。
Windows 上的默认控制台编码是代码页 850(不确定是否总是如此)。在你的情况下,你的文件是 CP 1252,你的控制台是 CP 850,这就是为什么你不能直接打印 '║'
(CP 1252 不包含 '║'
),但你可以使用原始特点。您可以使用 SetConsoleCP()
.
更改 Windows 上的控制台编码
在linux上,默认编码是UTF-8,更方便,因为它支持整个Unicode范围。 Ideone 使用 linux,因此它将使用 UTF-8。请注意,有添加的 HTTP 层和 HTML,但它们也为此使用 UTF-8。
我知道只有正字符 ASCII 值才能保证跨平台支持。
在Visual Studio2015年,我能做到:
cout << '\xBA';
并打印:
║
当我在 http://ideone.com 上尝试时,我没有打印任何东西。
如果我尝试使用文字字符直接打印:
cout << '║';
Visual Studio 发出警告:
warning C4566: character represented by universal-character-name '\u2551' cannot be represented in the current code page (1252)
然后打印:
?
当此命令在 http://ideone.com 上 运行 时,我得到:
14849425
我读到 wchar
s 可能为此提供跨平台方法。真的吗?或者我只是在扩展 ASCII 上运气不好?
这里有两个不同的概念。
第一个是语言环境之一,在Microsoft-ese中通常称为"code page"。语言环境定义了哪些视觉字符由哪个字节序列表示。在您的第一个示例中,无论您的程序以何种语言环境执行,它都会显示“║”字符,以响应字节 0xBA。
其他语言环境或代码页将针对相同的字节显示不同的字符。许多语言环境是多字节语言环境,其中可能需要几个字节才能显示单个字符。例如在UTF-8语言环境中,同一个字符║需要三个字节来显示:0xE2 0x95 0x91.
这里的第二个概念是源代码字符集之一,它来自编译源代码之前编辑的语言环境。当您在源代码中输入 ║ 字符时,如果您的编辑器使用 UTF-8 语言环境,它可能会被表示为 0xBA 字符,或者可能是 0xE2 0x95 0x91 序列。编译器在读取源代码时,只会看到实际的字节序列。一切都减少到字节。
幸运的是,所有的C++关键字都使用US-ASCII,所以用什么字符集来编写C++代码并不重要。直到你开始使用非拉丁字符。这会导致编译器警告,基本上是通知您,您使用的东西可能有效,也可能无效,具体取决于结果程序运行的最终语言环境。
首先,您的输入源文件有自己的编码。您的编译器需要能够读取此编码(可能需要 flags/settings 的帮助)。
对于一个简单的字符串,编译器可以自由地做它想做的事,但它必须产生一个 const char[]
。通常,编译器会尽可能保留源编码,因此程序中存储的字符串将具有输入文件的编码。在某些情况下,编译器会进行转换,例如,如果您的文件是 UTF-16(您不能在 char
s 中放入 UTF-16 字符)。
当你使用 '\xBA' 时,你写了一个原始字符,你自己选择了你的编码,所以没有来自编译器的编码。
当你使用'║'
时,'║'
的类型不一定是char
。如果字符在编译器字符集中不能表示为单个字节,则其类型将为 int
。在 Visual Studio 与 Windows-1252 源文件的情况下,'║'
不适合,因此它将是 int
类型并由 [=18 这样打印=].
您可以在字符串文字上强制使用前缀编码。 u8""
将强制使用 UTF-8,u""
UTF-16 和 U""
UTF-32。请注意,L""
前缀会给你一个宽字符 wchar_t
字符串,但它仍然依赖于实现。 Windows 上的宽字符是 UCS-2(每个字符 2 个字节),但 linux.
打印到控制台只取决于变量的类型。 cout <<
重载了所有常见类型,因此它的作用取决于类型。 cout <<
通常会将 char
字符串按原样提供给控制台(实际上是标准输入),而 wcout <<
通常会按原样提供 wchar_t
字符串。其他组合可能有转换或解释(比如输入 int
)。 UTF-8 字符串是 char
字符串,因此 cout <<
应该始终正确地提供它们。
接下来是控制台本身。控制台是一个完全独立的软件。你给它一些字节,它显示它们。 它一点也不关心你的程序。它使用自己的编码,并尝试使用此编码打印您输入的字节。
Windows 上的默认控制台编码是代码页 850(不确定是否总是如此)。在你的情况下,你的文件是 CP 1252,你的控制台是 CP 850,这就是为什么你不能直接打印 '║'
(CP 1252 不包含 '║'
),但你可以使用原始特点。您可以使用 SetConsoleCP()
.
在linux上,默认编码是UTF-8,更方便,因为它支持整个Unicode范围。 Ideone 使用 linux,因此它将使用 UTF-8。请注意,有添加的 HTTP 层和 HTML,但它们也为此使用 UTF-8。