C ++ - 将char转换为wchar_t。获得段错误

时间:2016-03-07 19:47:41

标签: c++ casting char istream wchar-t

我试图编写从istream中读取字符并将其转换为wchar_t的小程序。我得到了一个段错误。这是我的代码

#include <iostream>
using namespace std;

wchar_t read(istream &stream) {
 char *c;
 stream.read(c, sizeof(*c));
 cout << *c << endl;
 wchar_t retChar = static_cast<wchar_t>(*c);
 return retChar;
}

int main() {
 cout << "Write something" << endl;    
 read(cin);
}

我的逻辑是:

  1. 创建一个字符数组,因为只读取字符数组。
  2. 读取等于字符大小的字节数。即读取一个字符并将其存储在数组c中。
  3. 创建一个wchar_t并将该字符* c转换为wchar_t。
  4. return wchar_t
  5. 由于我遇到了段错误,所以这里显然有些不对劲。但我无法看到它。任何帮助将不胜感激。

    非常感谢

1 个答案:

答案 0 :(得分:1)

逐步完成代码,让OP了解正在发生的事情以及为什么它不会起作用。然后我们将看一个方法来做他们想要的尽可能接近他们意图的方法。然后提示如何在C ++世界中做得更好。

wchar_t read(istream &stream) {
 char *c;

声明指针c并且不指向任何指针。 c是未初始化的变量。可以把它想象成被邀请到史蒂夫的家去举办派对,但是没有人告诉你他住在哪里。可能性非常好,无论你去哪里,它都不会成为史蒂夫的家。

 stream.read(c, sizeof(*c));

sizeof(*c)将返回一个字符的大小。可能是8位和1个字节,但c仍未指向任何内容,因此这是Undefined Behaviour。没有人知道程序会做什么,但很可能它会将一个字节读入内存中的某个未知空间。也许这会导致崩溃,因为你无法在那里写。也许它会写一些允许写入的内容并搞砸其他内容。

 cout << *c << endl;

尝试打印c。如果程序在上面的read中存活,则几率很高,它也会存活下来,但这也是未定义的行为。

 wchar_t retChar = static_cast<wchar_t>(*c);

这将把一个字符的数据填充到一个宽字符中。它不会根据区域设置或任何其他字符编码进行转换。 char是一个数字代码,已被定义为被解释为一个字符。演员会愚蠢地把角色的价值放在一起,比如A&#39;和ASCII编码到retCharretChar现在等于65. 65可能意味着取决于wchar_t使用的编码。它可能仍然意味着A&#39;但对不起Ayn Rand,这是A可能不是A的一个案例。

 return retChar;
}

做OP正在尝试做的事情(并忽略暂时有更好的方法来做到这一点):

#include <iostream>
using namespace std;
wchar_t read(istream &stream) {
 char c[2];

分配一个字符数组。为什么?因为我所知道的最简单的方法是对字符串进行转换。

 stream.read(c, sizeof(c[0]));

c现在是一个衰减到指针的数组。我们只想读一个char,因此sizeof(c[0])获取数组中第一个元素的大小。

 c[1] = '\0';
 cout << c << endl;

Null终止并打印。

 wchar_t retChar[2];

再次,一个数组。

 mbstowcs(retChar, c, 1);

使用已设置的任何语言环境将一个字符从char转换为宽字符。在此处阅读有关区域设置的更多信息:http://en.cppreference.com/w/cpp/locale/setlocale

关于mbstowcs的文档:http://en.cppreference.com/w/cpp/string/multibyte/mbstowcs

 return retChar[0];
}

将所有人放在一起,快速测试一下:

#include <iostream>
#include <cstdlib>

wchar_t read(std::istream &stream)
{
    char c[2];
    stream.read(c, sizeof(c[0]));
    c[1] = '\0';
    std::cout << c << std::endl;
    wchar_t retChar[2];
    mbstowcs(retChar, c, 1);
    return retChar[0];
}

int main()
{
    std::wcout << read(std::cin) << std::endl;
}

这很简单,但在C ++世界中很难看,你应该尽可能坚持stringIn that case look into std::wstring_convert.