C++ - 将 char 转换为 wchar_t。出现段错误
C++ - Converting a char to wchar_t. Getting a segfault
我正在尝试编写从 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);
}
我这里的逻辑是:
- 创建一个字符数组,因为只读需要字符数组。
- 以等于字符大小的字节为单位读取。即读取一个字符并将其存储在数组 c.
- 创建一个 wchar_t 并将该字符 *c 转换为 wchar_t。
- return wchar_t
因为我遇到了段错误,所以这里显然有问题。我看不到它。任何帮助将不胜感激。
非常感谢
单步执行代码,让 OP 了解发生了什么以及为什么它不起作用。然后,我们将看看如何尽可能接近他们的意图来做他们想做的事情。然后提示如何在 C++ 世界中更好地做到这一点。
wchar_t read(istream &stream) {
char *c;
声明一个指针 c
并且不指向任何东西。 c
是一个未初始化的变量。可以把它想象成被邀请到史蒂夫家参加聚会,但没有人告诉你他住在哪里。无论你走到哪里,很有可能都不是史蒂夫的家。
stream.read(c, sizeof(*c));
sizeof(*c)
将 return 一个字符的大小。可能是 8 位和 1 字节,但是 c
仍然没有指向任何东西所以这是 Undefined Behaviour。不知道该程序将做什么,但很可能它会将一个字节读入内存中某个未知的 space 中。也许这会导致崩溃,因为你不能在那里写。也许它覆盖了允许覆盖的内容并搞砸了其他内容。
cout << *c << endl;
尝试打印出 c
。如果程序在上面的 read
中幸存下来,那么它也能幸存下来的可能性很大,但这也是未定义的行为。
wchar_t retChar = static_cast<wchar_t>(*c);
这实际上会将一个字符的数据值填充到一个宽字符中。它不会根据语言环境或任何其他字符编码进行转换。 char
是已定义为解释为字符的数字代码。强制转换会愚蠢地将字符值,比如 'A' 和 ASCII 编码放入 retChar
。 retChar
现在等于 65。65 可以表示任何内容,具体取决于 wchar_t
使用的编码。它可能仍然意味着 '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] = '[=17=]';
cout << c << endl;
Null 终止并打印。
wchar_t retChar[2];
同样,数组。
mbstowcs(retChar, c, 1);
使用已设置的任何语言环境将一个字符从字符转换为宽字符。在此处阅读有关语言环境的更多信息: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] = '[=21=]';
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++ 世界中很难看,您应该尽可能坚持使用 string
s。 In that case look into std::wstring_convert.
我正在尝试编写从 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);
}
我这里的逻辑是:
- 创建一个字符数组,因为只读需要字符数组。
- 以等于字符大小的字节为单位读取。即读取一个字符并将其存储在数组 c.
- 创建一个 wchar_t 并将该字符 *c 转换为 wchar_t。
- return wchar_t
因为我遇到了段错误,所以这里显然有问题。我看不到它。任何帮助将不胜感激。
非常感谢
单步执行代码,让 OP 了解发生了什么以及为什么它不起作用。然后,我们将看看如何尽可能接近他们的意图来做他们想做的事情。然后提示如何在 C++ 世界中更好地做到这一点。
wchar_t read(istream &stream) {
char *c;
声明一个指针 c
并且不指向任何东西。 c
是一个未初始化的变量。可以把它想象成被邀请到史蒂夫家参加聚会,但没有人告诉你他住在哪里。无论你走到哪里,很有可能都不是史蒂夫的家。
stream.read(c, sizeof(*c));
sizeof(*c)
将 return 一个字符的大小。可能是 8 位和 1 字节,但是 c
仍然没有指向任何东西所以这是 Undefined Behaviour。不知道该程序将做什么,但很可能它会将一个字节读入内存中某个未知的 space 中。也许这会导致崩溃,因为你不能在那里写。也许它覆盖了允许覆盖的内容并搞砸了其他内容。
cout << *c << endl;
尝试打印出 c
。如果程序在上面的 read
中幸存下来,那么它也能幸存下来的可能性很大,但这也是未定义的行为。
wchar_t retChar = static_cast<wchar_t>(*c);
这实际上会将一个字符的数据值填充到一个宽字符中。它不会根据语言环境或任何其他字符编码进行转换。 char
是已定义为解释为字符的数字代码。强制转换会愚蠢地将字符值,比如 'A' 和 ASCII 编码放入 retChar
。 retChar
现在等于 65。65 可以表示任何内容,具体取决于 wchar_t
使用的编码。它可能仍然意味着 '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] = '[=17=]';
cout << c << endl;
Null 终止并打印。
wchar_t retChar[2];
同样,数组。
mbstowcs(retChar, c, 1);
使用已设置的任何语言环境将一个字符从字符转换为宽字符。在此处阅读有关语言环境的更多信息: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] = '[=21=]';
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++ 世界中很难看,您应该尽可能坚持使用 string
s。 In that case look into std::wstring_convert.