C++ 在变量中输出 Unicode

C++ output Unicode in variable

我正在尝试输出一个包含 unicode 字符的字符串,它是通过 curl 调用接收到的。因此,我正在寻找类似于 u8L 选项的文字字符串,但不适用于变量。例如:

const char *s  = u8"\u0444";

但是,由于我有一个包含unicode字符的字符串,例如:

mit freundlichen Grüßen

当我想打印这个字符串时:

cout << UnicodeString << endl;

它输出:

mit freundlichen Gr??en

当我使用 wcout 时,它 return 是我:

mit freundlichen Gren

我哪里做错了,我怎样才能得到正确的输出。我 return 使用 RapidJSON 的输出,其中 return 的字符串为:

mit freundlichen Gr��en

请注意,该应用程序是 Ubuntu 上的 CGI 运行,响应浏览器请求

containing unicode characters

您忘记指定字符串包含哪个 unicode 编码。有 "narrow" UTF-8,它可以存储在 std::string 中并使用 std::cout 打印,还有更广泛的变体,但不能。了解您正在处理的编码是至关重要的。对于余下的回答,我假设您想使用 UTF-8。


When I want to print this string with:

cout << UnicodeString << endl;

编辑:

Important to note, the application is a CGI running on Ubuntu, replying on browser requests

这里的问题与在终端上打印略有不同。

  1. 您需要适当地设置 Content-Type 响应 header 否则客户端不知道如何解释响应。例如 Content-Type: application/json; charset=utf-8.
  2. 您仍然需要确保源字符串实际上是对应于 header 的正确编码。请参阅下面的旧答案以了解概述。
  3. 浏览器必须支持编码。大多数现代浏览器早就支持 UTF-8。

关于打印到终端的回答:

假设

  1. UnicodeString确实包含一个UTF-8编码的字符串
  2. 并且终端使用UTF-8编码
  3. 并且终端使用的字体具有您使用的字素

以上应该有效。

it outputs:

mit freundlichen Gr??en

那么看来至少上述假设之一不成立。

1.是否正确,您可以通过分别检查每个代码单元的数值并将其与您对 UTF-8 的预期进行比较来验证。如果 1. 不正确,那么您需要弄清楚字符串实际使用的是什么编码,然后转换编码,或者将终端配置为使用该编码。

  1. 终端通常(但不一定)使用系统本机编码。弄清楚你的终端/系统使用什么编码的第一步是弄清楚你首先使用的是什么终端/系统。详细信息可能在手册中。

    如果终端使用UTF-8,那么您需要将程序中的UFT-8字符串转换为终端使用的字符编码——除非该编码没有您要打印的字素。不幸的是,标准库不提供任意字符编码转换支持(有一些支持在窄 unicode 和宽 unicode 之间进行转换,但即使这种支持也被弃用了)。您可以找到 unicode 标准 here,尽管我想指出,使用现有的转换实现可以节省大量工作。

    如果终端的字符编码没有所需的 grapehemes - 或者如果您不想实现编码转换 - re-configure 终端使用 UTF-8。如果终端/系统可以配置为使用UTF-8,手册中应该有详细说明。

  2. 您应该能够测试字体本身是否具有所需的字素,只需在终端中键入字符并查看它们是否按应有的方式显示 - 尽管,如果终端编码没有字素,所以先检查一下。如果有必要,您的终端手册应该解释如何更改字体。也就是说,我希望 üß 存在于大多数字体中。

如果您使用 Windows,我建议您在 Windows 边界使用 Unicode UTF-16

在我看来 Windows 使用 Visual C++(至少达到 VS2015)std::cout cannot output UTF-8-encoded-text , 但 std::wcout 正确输出 UTF-16 编码的文本。

此可编译代码片段正确输出包含德语字符的字符串:

#include <fcntl.h>  
#include <io.h>  
#include <iostream>

int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);

    // ü : U+00FC
    // ß : U+00DF
    const wchar_t * text = L"mit freundlichen Gr\u00FC\u00DFen";

    std::wcout << text << L'\n';
}

注意 UTF-16 编码 wchar_t 字符串的使用。


更笼统地说,我建议您在 [=33] 中使用 UTF-8 编码(例如将文本存储在 std::string 中) =]跨平台 C++部分代码,并在Windows[=44=处转换为UTF-16编码文本]边界。

要在 UTF-8 和 UTF-16 之间转换,您可以使用 Windows API,例如 MultiByteToWideCharWideCharToMultiByte。这些是 C API,可以安全方便地包装在 C++ 代码中(更多详细信息可以在 this MSDN article, and you can find compilable C++ code here on GitHub 中找到)。

在我的系统上,以下命令产生了正确的输出。在你的系统上试试。我相信它会产生类似的结果。

#include <string>
#include <iostream>
using namespace std;

int main()
{
    string s="mit freundlichen Grüßen";
    cout << s << endl;
    return 0;
}

如果没问题,则表明网络传输不是 8 位干净的。

麦克。