D Unicode 字符串文字:无法打印特定的 Unicode 字符

D Unicode string literals: can't print specific Unicode character

我只是想学习来自 C++ 的 D。我确定这是非常基本的东西,但我找不到任何文档来帮助我。我正在尝试打印字符 à,即 U+00E0。我正在尝试将此字符分配给一个变量,然后使用 write() 将其输出到控制台。

我被告知 by this website U+00E0 在 UTF-8 中编码为 0xC3 0xA0,在 UTF-16 中编码为 0x00E0,在 UTF-32 中编码为 0x000000E0 .

请注意,对于我尝试过的所有操作,我尝试将 string 替换为 char[] 并将 wstring 替换为 wchar[]。我也尝试过在宽字符串后使用和不使用 wd 后缀。

这些方法return编译错误,"Invalid trailing code unit":

string str = "à";
wstring str = "à"w;
dstring str = "à"d;

这些方法打印出完全不同的字符 (Ò U+00D2):

string str = "\xE0";
string str = hexString!"E0";

所有这些方法都打印出类似 ˧á 的内容(注意 á ≠ à!),即 UTF-16 0x2E7 0x00E1:

string str = "\xC3\xA0";
wstring str = "\u00E0"w;
dstring str = "\U000000E0"d;

有什么想法吗?

D源代码需要编码为UTF-8。 我的猜测是您将 UTF-16 字符放入 UTF-8 源文件中。

例如

import std.stdio;
void main() {
    writeln(cast(char)0xC3, cast(char)0xA0);
}

将以 UTF-8 格式输出您要查找的字符。

然后你可以像这样硬编码:

import std.stdio;
void main() {
    string str = "à";
    writeln(str);
}

我确认它在我的 Windows 盒子上有效,所以现在要输入它作为答案。

在源代码中,如果您直接 copy/paste 字符,请确保您的编辑器将其保存为 utf8 编码。 D 编译器坚持这样做,所以如果它给出关于 utf 的编译错误,这可能就是原因。我从未使用过 c:b,但网络上的一个旧答案说编辑->编码...无论如何它都是编辑器中某处的设置。

或者,您可以将源代码中的字符替换为字符串中的 \uxxxx。不要使用 hexstring 的东西,它是用于二进制字节的,但是你的 "\u00E0" 的例子很好,并且适用于任何类型的字符串(不仅仅是你的例子中的 wstring)。

然后,在输出端,这取决于您的目标,因为程序只是输出字节,由接收程序正确解释它。既然你说你在 Windows,关键是将控制台代码页设置为 utf-8,这样它就知道你要做什么。实际上,同样的 C 函数也可以从 D 中调用。导致此程序:

import core.sys.windows.windows;
import std.stdio;

void main() {
    SetConsoleOutputCP(65001);
    writeln("Hi \u00E0");
}

打印成功。在旧的 Windows 版本上,您可能需要更改字体才能看到字符(与它显示的通用框相反,因为某些字体没有所有字符),但在我的 Windows 10个框,它只是使用默认字体。

顺便说一句,从技术上讲,控制台代码页是一个共享设置(在 运行 程序退出后,您仍然可以点击控制台上的属性 window 并查看那里反映的更改)和当您的程序退出时,您或许应该将其重新设置。您可以在启动时使用 get 函数 ( https://docs.microsoft.com/en-us/windows/console/getconsoleoutputcp ) 获取它,将其存储在本地 var 中,然后在退出时将其重新设置。您可以在启动时 auto ccp = GetConsoleOutputCP(); SetConsoleOutputCP(65005;) scope(exit) SetConsoleOutputCP(ccp); - 当函数退出时范围退出将 运行 ,所以在 main 中这样做会很方便。如果需要,只需添加一些错误检查。

Microsoft 文档没有说明如何将其重新设置,因此它实际上可能并不重要,但我仍然想提一下以防万一。但它被共享和持久化的知识也有助于调试 - 如果它在你评论它之后起作用,那不是因为代码不是必需的,只是因为它之前设置并且尚未取消设置!

请注意,从 IDE 中 运行 可能不完全相同,因为 IDE 通常通过管道输出而不是 运行 直接输出到 Windows 控制台。如果发生这种情况,让我知道,我们也可以为未来的读者写一些相关的东西。但您也可以打开自己的控制台副本(运行 IDE 之外的程序),它应该会正确显示给您。