【问题标题】:C++ output Unicode in variableC++ 在变量中输出 Unicode
【发布时间】:2018-07-13 08:52:33
【问题描述】:

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

const char *s  = u8"\u0444";

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

mit freundlichen Grüßen

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

cout << UnicodeString << endl;

它输出:

mit freundlichen Gr??en

当我使用wcout 时,它返回给我:

mit freundlichen Gren

我做错了什么以及如何获得正确的输出。我用RapidJSON返回输出,它返回字符串为:

mit freundlichen Gr��en

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

【问题讨论】:

  • std::wcout,尽管这可能只会让编码难题更进一步。
  • @Bathsheba,我已经尝试过使用 wcout,结果是:mit freundlichen Gren
  • 您需要将字符串从其当前编码(可能是UTF-8)转换为您的输出设备支持的编码(不知道那是什么)。没有快速的解决方案,你必须做一些工作。
  • @john,我的输出设备与请求的接收者一样吗?我猜它实际上也是 UTF8..?
  • @ThomasvanHesteren 打印出您的字符串的字节值,并将它们张贴在这里。这将告诉您的字符串使用什么编码。如果您的输出设备支持 UTF-8 并且您看到 ??在那种表明你的字符串不是 UTF-8 的输出中。 Somhow 需要进行某种转换,首要任务是弄清楚那是什么。

标签: c++ unicode unicode-string


【解决方案1】:

在我的系统上,以下会产生正确的输出。在您的系统上尝试一下。我相信它会产生类似的结果。

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

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

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

迈克。

【讨论】:

    【解决方案2】:

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

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

    此可编译代码 sn-p 正确输出包含德语字符的字符串:

    #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 字符串。


    一般来说,我建议您在 跨平台 中使用 UTF-8 编码(例如将文本存储在 std::strings 中) C++ 部分代码,并在 Windows 边界处转换为 UTF-16 编码 文本。

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

    【讨论】:

      【解决方案3】:

      包含 unicode 字符

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


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

      cout << UnicodeString << endl;
      

      编辑:

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

      这里的关注点与在终端上打印略有不同。

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

      关于打印到终端的答案:

      假设

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

      以上应该可以工作。

      它输出:

      mit freundlichen Gr??en
      

      那么看来上述假设中至少有一个不成立。

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

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

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

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

      2. 1234563有字素,所以先检查一下。如果有必要,您的终端手册应说明如何更改字体。也就是说,我希望üß 存在于大多数字体中。

      【讨论】:

      • 代码是CGI,以JSON格式输出到发送请求的浏览器
      猜你喜欢
      • 2011-03-10
      • 1970-01-01
      • 2022-01-10
      • 2012-01-13
      • 1970-01-01
      • 2013-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多