我想显示无穷大符号
∞
,它具有Unicode U+221E
。我目前正在使用 fmt 库,它应该有很多支持并且是跨平台的。
fmt::print("", fmt::styled("∞ >", fmt::emphasis::bold | fg(fmt::color::aquamarine)));
我得到以下输出:
? >
我也尝试过设置:
setlocale(LC_ALL, "en_US.UTF-8");
没有帮助。我使用的是 Windows 11 x64。
警告:
warning C4566: character represented by universal-character-name '\u221E' cannot be represented in the current code page (1252)
MS Visual Studio 2022 IDE。
我应该在项目属性中更改字符集吗?当前设置为:使用 Unicode 字符集,第二个选项是:使用多字节字符集。
/utf-8
标志进行编译。除此之外,这会将字符串文字编码设置为 UTF-8。它由 {fmt} 检测到,它使用 Unicode API 写入控制台。一般来说,更改区域设置不会有帮助,因为问题在其他地方:
出于类似的原因,使用宽字符串也无济于事。
问题出在编译期间,而不是运行时。 您在字符串文字中按原样指定
∞
字符,但编译器正在使用代码页 1252 解析源代码,该代码页不支持 Unicode U+221E(并且该字符无法存储在单个 char
中)无论如何)。因此,在编译过程中您会丢失
∞
,在 fmt 库看到它之前,它会被
?
替换。
setlocale()
对此问题没有影响,因为它仅在运行时处理。项目的字符集选项对这个问题也没有影响,因为它只影响基于
TCHAR
的API的编译,没有其他影响。所以,你有2个选择:
/utf8
编译器标志进行编译。
fmt::print(L"", fmt::styled(L"∞ >", fmt::emphasis::bold | fg(fmt::color::aquamarine)));
fmt
没有任何关系。对于初学者,在 C++11 及更高版本上,您可以使用以下代码将
cout
、
cerr
等使用的字符集更改为 UTF8:
#include <locale>
template <typename StreamT>
void set_utf8_locale(StreamT& stream) {
std::locale loc(std::locale(), new std::codecvt_utf8<typename StreamT::char_type>());
stream.imbue(loc);
}
set_utf8_locale(std::cout);
然后您需要确保您的编译器将字符串存储为 UTF8。您可以通过在字符串前添加前缀 u8
来实现此目的,例如
u8"abc"
。在 C++20 及更高版本中,这会产生与 const char* 不同的类型,因此您需要使用
reinterpret_cast<const char*>(u8"abc")
来获取正确的类型。Linux 和 MacOS 使用 UTF8 进行输出,因此您无需为这些平台担心这一点。
C4566。出现这种情况是因为 Unicode 格式,尤其是非标准 ASCII 字符 在 C++ 中变得疯狂。
这个:char inf = '∞'
因为没有分配足够的位而中断。同样的事情也发生在
string inf = '∞'
、
string inf = L'∞'
等等..最方便的做法是使用宽字符(
wchar_t
)和数组,以便能够呼吸。 可能还有另一种方法可以做到这一点,但这是我使用 inifity 符号/Unicode 符号的方法。
wchar_t inf[] = L"\u221e"; // ∞ in unicode is U+221E
窄字符串(一字节字符)会转换为多字节字符,而宽字符串(两字节字符)则不会。这是因为 L 将字符串转换为宽文字,用外行人的话说,这为更多字符腾出了空间位,这样它们就不会变得奇怪..