2011-08-12 31 views
0

我有做这样的事情代码:如何检查是否到wchar_t的铸造“失败”

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在Specials表中。当系统不能将数据流解码为正确的符号时,它被用来指示问题。它 是最常见的,当一个字体不包含字符,但 也看到当数据是无效的,不匹配任何字符:

所以我有2个问题:1。 是否有正确的方法来做到这一点很好? 2.是否有其他字符,如替换字符,表示转换失败?

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

+1

只要你的平台的'wchar_t'至少有16位宽,演员就不能*失败*。对于'sizeof(wchar_t)> = sizeof(char16_t)''的静态断言将会诀窍,而不需要运行时代码。 –

+0

我不认为这就是他的意思是“失败”。当然,他的意思是超出了C++的范围。 –

+0

是的,失败我的意思是获取替换字符,而不是意义上的文件失败打开失败 – NoSenseEtAl

回答

3

不这样工作。 wchar_tchar16_t都是C++中的整数类型。从一个到另一个按照通常的整数转换规则进行投射,它不会尝试以任何方式在字符集之间进行转换,或者验证任何内容是否为真正的unicode代码点。

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

前提是:

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

然后你的代码应该可以正常工作。它不会验证输入,但只需复制这些值。

3

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

为什么ICU4C?

C和C++语言和许多操作系统环境不提供对Unicode和符合标准的文本处理服务的完全支持。尽管有些平台确实提供了很好的Unicode文本处理服务,但便携式应用程序代码无法使用它们。 ICU4C库填补了这一空白。 ICU4C为应用软件全球化要求提供了一个开放,灵活,便携的基础。 ICU4C密切关注行业标准,包括Unicode和CLDR(通用语言环境数据存储库)。

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

1

一投不能不既会产生任何替换字符。代码中的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值,如果你需要。

2

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

*编辑:我看你在Linux上;尽管Windows用户可以从中受益,但我会将答案留在这里。