我想知道这样做是否安全?
wchar_t wide = /* something */;
assert(wide >= 0 && wide < 256 &&);
char myChar = static_cast<char>(wide);
Run Code Online (Sandbox Code Playgroud)
如果我很确定宽字符将落在ASCII范围内.
Mar*_*som 10
assert用于确保在调试模式下某些事情是真的,而不会在发布版本中产生任何影响.最好使用一个if语句,并对超出范围的字符有一个替代计划,除非获得超出范围的字符的唯一方法是通过程序错误.
此外,根据您的字符编码,您可能会发现Unicode字符0x80到0xff与它们的char版本之间存在差异.
geo*_*car 10
您正在寻找wctomb():它符合ANSI标准,因此您可以依赖它.它甚至在wchar_t使用255以上的代码时也能工作.你几乎肯定不想使用它.
wchar_t 是一个完整的类型,所以如果你真的这样做,你的编译器不会抱怨:
char x = (char)wc;
Run Code Online (Sandbox Code Playgroud)
但因为它是一个整体类型,所以绝对没有理由这样做.如果你不小心阅读了Herbert Schildt的C:The Complete Reference,或任何基于它的C书,那么你就完全被误导了.字符应该是类型int 或更好.这意味着你应该写这个:
int x = getchar();
Run Code Online (Sandbox Code Playgroud)
而不是这个:
char x = getchar(); /* <- WRONG! */
Run Code Online (Sandbox Code Playgroud)
就整体类型而言,char是没有价值的.你不char应该创建带有类型参数的函数,也不应该创建类型的临时变量,char同样的建议wchar_t也是如此.
char*对于字符串来说可能是一个方便的typedef,但是将它想象为"字符数组"或"指向字符数组的指针"是一个新手错误 - 尽管cdecl工具说的是什么.将它视为一个真实的字符数组,像这样废话:
for(int i = 0; s[i]; ++i) {
wchar_t wc = s[i];
char c = doit(wc);
out[i] = c;
}
Run Code Online (Sandbox Code Playgroud)
是荒谬的错.它不会做你想要的; 它会以微妙和严肃的方式划分,不同的表现在不同的平台,你肯定会混淆了地狱,你的用户.如果你看到这个,你正在尝试重新实现wctombs(),这已经是ANSI C的一部分,但它仍然是错误的.
你真的在寻找iconv(),它将一个字符串从一个编码(即使它被打包成一个wchar_t数组)转换成另一个编码的字符串.
现在去看看这个,了解iconv有什么问题.
小智 8
一个简单的方法是:
wstring your_wchar_in_ws(<your wchar>);
string your_wchar_in_str(your_wchar_in_ws.begin(), your_wchar_in_ws.end());
char* your_wchar_in_char = your_wchar_in_str.c_str();
Run Code Online (Sandbox Code Playgroud)
我多年来一直使用这种方法:)
我写了一个简短的函数,将wchar_t数组打包为char数组。不在ANSI代码页(0-127)上的字符替换为'?' 字符,并且可以正确处理代理对。
size_t to_narrow(const wchar_t * src, char * dest, size_t dest_len){
size_t i;
wchar_t code;
i = 0;
while (src[i] != '\0' && i < (dest_len - 1)){
code = src[i];
if (code < 128)
dest[i] = char(code);
else{
dest[i] = '?';
if (code >= 0xD800 && code <= 0xD8FF)
// lead surrogate, skip the next code unit, which is the trail
i++;
}
i++;
}
dest[i] = '\0';
return i - 1;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
136005 次 |
| 最近记录: |