【问题标题】:How to check if the casting to wchar_t "failed"如何检查转换为 wchar_t 是否“失败”
【发布时间】:2011-08-12 08:47:52
【问题描述】:

我有一个代码可以做这样的事情:

char16_t msg[256]={0};
//...
wstring wstr;
for (int i =0;i<len;++i)
    {
        if((unsigned short)msg[i]!=167)
                wstr.push_back((wchar_t) msg[i]);
            else
                wstr.append(L"_<?>_");
    }

如您所见,它使用了一些相当难看的硬编码(我不确定它是否有效,但它适用于我的数据)来确定 wchar_t 转换是否“失败”(即替换字符的值) 来自维基:

替换字符 �(通常是黑色菱形与白色菱形 问号)是在代码点的 Unicode 标准中找到的符号 特价表中的 U+FFFD。它用于指示出现问题时 系统无法将数据流解码为正确的符号。它 当字体不包含字符时最常见,但 当数据无效且不匹配任何字符时也会看到:

所以我有两个问题: 1.有没有合适的方法可以很好地做到这一点? 2. 是否有其他字符(如替换字符)表示转换失败?

编辑:我在 linux 上使用 gcc,所以 wchar_t 是 32 位的,我需要这个演员表工作的原因是因为奇怪的 wstrings 杀死了我的 glog 库。 :) wcout 也死了。 :( :)

【问题讨论】:

  • 只要您平台的 wchar_t 至少为 16 位宽,转换就不会失败sizeof(wchar_t) &gt;= sizeof(char16_t) 的静态断言可以解决问题,不需要运行时代码。
  • 我不认为这就是他所说的“失败”。当然,他的意思超出了C++的范围。
  • 是的,失败是指获取替换字符,而不是感觉文件打开失败中的失败

标签: c++ unicode


【解决方案1】:

不能那样工作。 wchar_tchar16_t 在 C++ 中都是整数类型。从一个转换到另一个遵循整数转换的常用规则,它不会尝试以任何方式在字符集之间进行转换,也不会验证任何东西都是真正的 unicode 代码点。

任何替换字符都必须来自比简单转换更复杂的代码(当然也可以来自原始输入)。

前提是:

  1. msg 中的输入是 BMP 中的代码点序列
  2. wchar_t 在您的实现中至少为 16 位,并且您的实现使用的宽字符集是 Unicode(或 Unicode 的 16 位版本,无论是仅 BMP 还是 UTF-16)。

那么您拥有的代码应该可以正常工作。但是,它不会验证输入,只是复制值。

【讨论】:

    【解决方案2】:

    如果您想在 C++ 中实际处理 Unicode 字符串(而不仅仅是 16 位值的序列),您应该使用 International Components for Unicode (ICU) 库。引用FAQ

    为什么选择 ICU4C?

    C 和 C++ 语言以及许多操作系统环境不提供对 Unicode 和符合标准的文本处理服务的完全支持。即使某些平台确实提供了良好的 Unicode 文本处理服务,可移植应用程序代码也无法使用它们。 ICU4C 库填补了这一空白。 ICU4C 为应用程序提供了一个开放、灵活、可移植的基础,用于满足其软件全球化需求。 ICU4C 密切跟踪行业标准,包括 Unicode 和 CLDR(通用区域设置数据存储库)。

    作为副作用,如果转换失败,您会得到正确的错误报告...

    【讨论】:

      【解决方案3】:

      如果您不介意特定于平台的代码,Windows 有 MultiByteToWideChar API。

      *编辑:我看到你在 linux 上;我会在此处留下我的答案,以防 Windows 用户从中受益。

      【讨论】:

        【解决方案4】:

        演员不能失败,也不会产生任何替换字符。代码中的 167 值并不表示强制转换失败,它意味着只有代码作者知道的其他内容。

        仅供参考,Unicode 代码点 167 (0x00A7) 是 section sign: §.也许这会敲响一些关于代码应该做什么的钟声。

        虽然我不知道它是什么,但考虑重写它:

        wchar_t msg[256];
        ...
        wstring wstr(msg, wcslen(msg));
        

        char16_t msg[256];
        ...
        u16string u16str(msg, wcslen(msg));
        

        然后根据需要对 167 值做一些事情。

        【讨论】:

          猜你喜欢
          • 2014-01-30
          • 1970-01-01
          • 2016-09-17
          • 2012-06-07
          • 1970-01-01
          • 2012-07-11
          • 2016-08-08
          • 2017-01-02
          • 2011-12-02
          相关资源
          最近更新 更多