【问题标题】:C++ - Converting a char to wchar_t. Getting a segfaultC++ - 将 char 转换为 wchar_t。获得段错误
【发布时间】:2016-03-07 19:47:41
【问题描述】:

我正在尝试编写从 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. 返回 wchar_t

由于我遇到了段错误,这里显然有问题。虽然我看不到。任何帮助将不胜感激。

非常感谢

【问题讨论】:

  • 你永远不会为你的char*分配内存。比你没有真正转换任何东西 - 你只是在没有任何转换的情况下转换类型。
  • 您的段错误与转换为wchar_t 无关。你得到是因为你的read 函数的前两行。您正在读取一个未初始化(无效)的指针(更不用说 - 在同一行中取消引用所述指针。
  • 你也可以声明你想要存储的东西,然后在对read的调用中将其转换为char*
  • 您没有在任何地方创建字符数组。
  • 另外,为什么不直接用wifstream 打开文件并将数据读入wstring

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


【解决方案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”和ASCII编码)放入retCharretChar 现在等于 65。根据wchar_t 使用的编码,65 可能意味着任何东西。它可能仍然表示“A”,但抱歉 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 转换为宽 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++ 世界中很丑陋,您应该尽可能坚持使用strings。 In that case look into std::wstring_convert.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 2018-01-07
    相关资源
    最近更新 更多