【问题标题】:Portable wchar_t in C++C++ 中的可移植 wchar_t
【发布时间】:2010-10-02 19:13:37
【问题描述】:

C++ 中有可移植的 wchar_t 吗?在 Windows 上,它的 2 个字节。其他一切都是4个字节。我想在我的应用程序中使用 wstring,但是如果我决定移植它,这将导致问题。

【问题讨论】:

标签: c++ windows portability wchar-t wstring


【解决方案1】:

如果您正在处理程序内部的使用,请不要担心; A 类中的 wchar_t 与 B 类中的相同。

如果您计划在 Windows 和 Linux/MacOSX 版本之间传输数据,您需要担心的不仅仅是 wchar_t,您需要想出处理所有细节的方法。

您可以定义一个类型,您将在任何地方定义为四个字节,并实现您自己的字符串等(因为 C++ 中的大多数文本处理都是模板化的),但我不知道它的效果如何你的需求。

类似typedef int my_char; typedef std::basic_string<my_char> my_string;

【讨论】:

  • 你需要 char_traits 来做这件事,而且你不能专门化 std::char_traits (每个命名空间标准规则)。
  • 另外,您可以在内部简单地使用 wchar_t/wstring。在外部,您使用 UTF-8 绕过字节序混乱。在 I/O 上,使用 sizeof(wchar_t) 专用的模板函数在 wchar_t 和 UTF-8 之间进行转换。
  • -1 使用 my_char 是个坏主意。您可以将字符串写入流,但您无能为力
【解决方案2】:

“便携式 wchar_t”是什么意思?到处都有一个 16 位宽的 uint16_t 类型,这通常是可用的。但这当然还不能构成一个字符串。字符串必须知道其编码才能理解length()、substring() 等函数(因此在使用 utf8 或 16 时,它不会在代码点中间剪切字符)。我知道您可以使用一些与 unicode 兼容的字符串类。所有都可以免费用于商业程序(Qt 将在几个月内免费兼容商业程序,当 Qt 4.5 发布时)。

ustring 来自 gtkmm 项目。如果您使用 gtkmm 编程或使用 glibmm,那应该是首选,它在内部使用 utf-8。 Qt 还有一个字符串类,叫做 QString。它以utf-16 编码。 ICU 是另一个创建可移植 unicode 字符串类的项目,并且有一个 UnicodeString 类,它在内部似乎是用 utf-16 编码的,就像 Qt 一样。不过没用过那个。

【讨论】:

  • 其实length(), substring() 和Co. 对编码一无所知,他们只是看编码单元的大小并进行处理。
  • @Mihai,确定是 std::string 函数的情况。但这就是它不能用于 utf8 等的原因。
  • @Johannes Schaub:但答案指出“字符串必须知道其编码才能理解长度()、子字符串()等函数”所以不,它不必知道。您可以在不知道编码的情况下根据代码单元工作,您所需要的只是代码单元的大小。
  • @Mihai,如果你使用 utf8,那么代码单元有 8 位大小 - 但是要计算字符串的长度,知道这根本不够。您必须考虑连续字节之类的东西。否则,您将不会获得字符串的长度,而只会获得代码单元计数。当然,对于像 ASCII 这样的固定长度编码,这无关紧要,知道代码单元的大小才是最重要的。
  • 这取决于“字符串的长度”是什么意思。如果您要分配内存或报告磁盘使用情况,那么 代码单元的数量很重要。如果您关心 字符 的数量,则确实需要知道编码。如果您关心您的字符串在文本终端中占用了多少 列,那就另当别论了。
【解决方案3】:

提议的 C++0x 标准将具有 char16_t 和 char32_t 类型。在此之前,您将不得不对非wchar_t 字符类型使用整数。

#if defined(__STDC_ISO_10646__)
    #define WCHAR_IS_UTF32
#elif defined(_WIN32) || defined(_WIN64)
    #define WCHAR_IS_UTF16
#endif

#if defined(__STDC_UTF_16__)
    typedef _Char16_t CHAR16;
#elif defined(WCHAR_IS_UTF16)
    typedef wchar_t CHAR16;
#else
    typedef uint16_t CHAR16;
#endif

#if defined(__STDC_UTF_32__)
    typedef _Char32_t CHAR32;
#elif defined(WCHAR_IS_UTF32)
    typedef wchar_t CHAR32;
#else
    typedef uint32_t CHAR32;
#endif

根据标准,您需要将char_traits 专门用于整数类型。但在 Visual Studio 2005 上,我已经摆脱了 std::basic_string<CHAR32> 没有特殊处理。

我打算使用 SQLite 数据库。

那么您需要使用 UTF-16,而不是 wchar_t。

SQLite API 也有一个 UTF-8 版本。您可能想要使用它而不是处理 wchar_t 差异。

【讨论】:

    【解决方案4】:

    我的建议。使用 UTF-8 和 std::string。宽弦不会给你带来太多的附加值。因为您无论如何都不能将宽字符解释为字母,因为某些字符是从几个 unicode 代码点创建的。

    所以在任何地方使用 UTF-8 并使用好的库来处理自然语言。例如 Boost.Locale。

    坏主意:定义像 typedef uint32_t mychar; 这样的东西是不好的。由于您不能将 iostream 与它一起使用,因此您无法创建例如基于此字符的字符串流,因为您将无法在其中写入。

    例如,这是行不通的:

    std::basic_ostringstream<unsigned> s;
    ss << 10;
    

    不会给你创建一个字符串。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-08
      • 2010-10-29
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      相关资源
      最近更新 更多