【问题标题】:Print unicode char打印 unicode 字符
【发布时间】:2018-06-22 03:42:43
【问题描述】:

我在 C++ 中尝试了一个非常简单的代码:

#include <iostream>
#include <string>

int main()
{
  std::wstring test = L"asdfa-";
  test += u'ç';
  std::wcout << test;
}

但结果是:

asdfa-?

无法使用 cout 或 wcout 打印 'ç',我怎样才能正确打印此字符串?

操作系统:Linux。

Ps:我用wstring而不是string,因为有时候我需要计算字符串的长度,这个长度必须和屏幕上的一样。

Ps:我需要连接 unicode char,它不能在字符串构造函数上。

【问题讨论】:

  • 目标平台是什么?
  • Linux,我编辑了这篇文章。谢谢菲尔·布鲁贝克。
  • 看看这是否有帮助:stackoverflow.com/q/12015571/6610379
  • 我看到了这个帖子,对我没有帮助。
  • 源文件的编码是什么?你的编译器 assume 是什么?如果将u'ç' 替换为u'\xe7' 会发生什么?

标签: c++ linux unicode char c++14


【解决方案1】:

首先,确实起作用:

#include <iostream>
#include <string>

int main() {
    std::string test = "asdfa-";
    test += "ç";
    std::cout << test;
}

我在这里只使用常规字符串,让 C++ 将所有内容保存在 UTF-8 中。我想你已经知道这会起作用,因为你提到你想要连接 ç 而不是仅仅将它留在字符串构造函数中。

在 C++ 中处理 charchar16_tchar32_twchar_t 从来没有真正有趣过。您必须小心使用 LuU 前缀。

但是,在可能的情况下,如果您处理 utf-8 字符串并避免使用字符,通常可以让事情变得更好。而且由于大多数控制台(旧的 Windows 机器可能除外)都很好地理解 utf-8,因此这种方法通常效果最好。因此,如果您有宽字符,请查看是否可以将它们转换为常规的 std::string 对象并在该域中工作。

【讨论】:

  • 对我来说问题是我需要计算字符串长度,而'ç'使长度与屏幕上的打印长度不同。
  • 为什么需要计算字符串的长度?该操作通常是代码异味。大多数应用程序不需要它。反正那也太乱了……,你是指字节数,字符数,还是字素数?
  • @Alex 如果您需要计算字符单元格中屏幕上打印内容的长度,那么您就不走运了。一个 Unicode 字符(== 代码点,Linux 上的 C 和 C++ 中的 wchar_t)可能占用 0、1 或更多个单元格,一个单元格可能包含 1 个或多个 Unicode 字符。使用标准 C++ 无法确定任何这些。
【解决方案2】:

处理此问题的一种一般方法是:

  1. 输入(使用当前语言环境从多字节转换为宽)

  2. 您的应用:使用宽字符串

  3. 输出或保存到文件(从宽字节转换为多字节)

对于字符数、子字符串等宽字符串操作,有 wcsXXX 类函数。

【讨论】:

    【解决方案3】:

    如果您在 Linux 上使用 libstdc++:您忘记了程序开头的重要调用

    std::locale::global(std::locale(""));
    

    这是假设您使用的是 Linux 并且您的语言环境支持 UTF-8。

    如果您使用libc++:忘记使用wstreams。这个库不以有用的方式支持宽字符的 I/O(即像 libstdc++ 那样转换为 UTF-8)。

    Windows 有一套完全独立的关于 Unicode 的怪癖。如果您不必与他们打交道,那您很幸运。

    demo with gcc/libstdc++ and a call to std::locale

    demo with gcc/libstdc++ and no call to std::locale

    不同版本的clang/libc++在这个例子中表现不同:有些输出?而不是非ascii字符,有些什么也不输出;有些在调用 std::locale 时会崩溃,有些则不会。没有人做正确的事,即打印ç,或者我只是没有找到一个有效的方法。如果您需要与语言环境或 wchar_t 相关的任何内容,我不建议您使用 libc++。

    【讨论】:

      【解决方案4】:

      我使用转换函数解决了这个问题:

      #include <iostream>
      #include <string>
      #include <codecvt>
      #include <locale>
      
      std::string wstr2str(const std::wstring& wstr) {
        std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
        return myconv.to_bytes(wstr);
      }
      
      int main()
      {
        std::wstring test = L"asdfa-";
        test += L'ç';
        std::string str = wstr2str(test)
        std::cout << str;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-06-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-23
        • 2014-08-01
        相关资源
        最近更新 更多