11
4

4 回答 4

7

Unicode 字符\u2780超出char数据类型的范围。你应该已经收到了这个编译器警告来告诉你:(至少我的 g++ 4.7.3 给出了它)

test.cpp:6:13: warning: multi-character character constant [-Wmultichar]

如果您想将 U+2780 之类的字符作为单个单元使用,则必须使用 widechar 数据类型wchar_t,或者如果您有幸能够使用 C++11char32_tchar16_t. 请注意,一个 16 位单元不足以表示所有 Unicode 字符。

如果这对您不起作用,可能是因为默认的“C”语言环境不支持非 ASCII 输出。要解决该问题,您可以setlocale在程序开始时调用;这样您就可以输出用户语言环境支持的全部字符:(可能支持也可能不支持您使用的所有字符)

#include <clocale>
#include <iostream>

using namespace std;

int main() {
    setlocale(LC_ALL, "");
    wcout << L'\u2780';
    return 0;
}
于 2013-06-05T16:15:44.913 回答
4

当你写

cout << "\u2780";

编译器将 \u2780 转换为执行字符集中该字符的适当编码。那可能是 UTF-8,因此字符串最终有四个字节(三个用于字符,一个用于空终止符)。

如果您想在运行时生成字符,那么您需要一些方法在运行时执行与编译器在编译时执行的相同的 UTF-8 转换。


C++11 提供了一个方便的wstring_convert模板和 codecvt facets 可以做到这一点,但是 gcc 附带的标准库实现 libstdc++ 尚未开始实现它们(从 gcc 4.8 开始)。下面展示了如何使用这些功能,但您需要使用不同的标准库实现或等待 libstdc++ 实现它们。

#include <codecvt>

int main() {
  char32_t base = U'\u2780';

  std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
  std::cout << convert.to_bytes(base + 5) << '\n';
}

您还可以使用任何其他可用的方法来生成 UTF-8。例如,iconv、ICU 和手动使用 C++11 之前的 codecvt_byname 方面都可以工作。(我没有展示这些示例,因为该代码将比 . 所允许的简单代码涉及更多wstring_convert。)


一种适用于少量字符的替代方法是使用文字创建一个字符串数组。

char const *special_character[] = { "\u2780", "\u2781", "\u2782",
  "\u2783", "\u2784", "\u2785", "\u2786", "\u2787", "\u2788", "\u2789" };

std::cout << special_character[i] << '\n';
于 2013-06-06T19:47:12.427 回答
1

由于 C++11 §2.14.3/1,该程序打印一个整数:

多字符文字或包含无法在执行字符集中表示的单个 c-char 的普通字符文字是有条件的,具有 int 类型,并具有实现定义的值。

执行字符集就是char可以表示的,即ASCII。

你得到的是 14851712,或者十六进制的 e29e80,它是 U+2780 的 UTF-8 表示。将 UTF-8(一种多字节编码)放入 anint中既疯狂又愚蠢,但这就是您从“有条件支持的、实现定义的”功能中得到的。

要获取 UTF-32 值,请使用U'\u2780'. 第一个U指定char32_t类型和 UTF-32 编码(即最多 31 位但没有代理对)。第二个\u指定包含代码点的通用字符名称。要获得一个据称与 , 兼容的值wcout,请使用L'\u2780',但这不一定使用 Unicode 运行时值,也不一定会获得超过两个字节的存储空间。

至于可靠地操作和打印 Unicode 代码点,正如其他答案所指出的那样,C++ 标准还没有完全实现。Joni 的回答是最好的方法,但它仍然假设编译器和用户的环境使用相同的语言环境,这通常不是真的。

您还可以使用在源代码中指定 UTF-8 字符串,u8"\u2780"并使用类似std::locale::global( std::locale( "en_US.UTF-8" ) );. 但这仍然有粗糙的边缘。Joni 建议使用 C 接口std::setlocale<clocale>不是 C++ 接口std::locale::global<locale>这是在 OS X 和其他平台上的 GCC 中破坏 C++ 接口的一种解决方法。这些问题对平台足够敏感,以至于您的 Linux 发行版很可能已将补丁放入他们自己的 GCC 包中。

于 2013-06-16T02:35:15.927 回答
0

在 Linux 中,我以最天真的方式成功地直接打印出任何 unicode:

std::cout << "ΐ , Α, Β, Γ, Δ, ,Θ , Λ, Ξ, ... ±, ... etc"
于 2017-01-09T10:51:04.053 回答