将wchar_t转换为char

Che*_*eng 34 c++

我想知道这样做是否安全?

wchar_t wide = /* something */;
assert(wide >= 0 && wide < 256 &&);
char myChar = static_cast<char>(wide);
Run Code Online (Sandbox Code Playgroud)

如果我很确定宽字符将落在ASCII范围内.

Igo*_*aka 28

为什么不使用库例程wcstombs.

  • 这是为了字符串.我只想转换一个char. (2认同)

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有什么问题.

  • 我不认为这个答案的开场白被提出的问题证明是合理的。在我看来,他要求将 16 位值截断为 8 位值;他在任何地方都没有询问保留语义。 (2认同)
  • 此外,他正在处理的 `char` 值可能是 `char`,因为它来自,比如说,作用于 `char[]` 的 `cin.getline()`。 (2认同)

小智 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)

我多年来一直使用这种方法:)


cva*_*ode 5

我写了一个简短的函数,将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)