0

我在打印 std::string 的字节表示时遇到奇怪的错误,而 std::wstring 工作正常。

std::string str = "mystring";
unsigned short* vtemp = (unsigned short*)str.c_str();
for(int i=0; i<str.length(); ++i)
{
    cout << (unsigned short)((unsigned char)vtemp[i]) << " ";
}
cout << endl;

Incorrect Output: 109 115 114 110 0 204 204 204


wstring wstr(str.length(), L' ');
std::copy(str.begin(), str.end(), wstr.begin());

vtemp = (unsigned short*)wstr.c_str();

for(int i=0; i<wstr.length(); ++i)
{
    cout << (unsigned short)((unsigned char)vtemp[i]) << " ";
}
cout << endl;

Correct Output: 109 121 115 116 114 105 110 103

在第一种情况下,每个备用字符都被跳过。为什么这样?

该程序在项目设置中启用了 unicode 字符集的 Windows 上运行。

4

5 回答 5

5

这是因为这条线:

unsigned short* vtemp = (unsigned short*)str.c_str();

unsigned short是两个字节长。char是一个字节长。您正在设置一个unsigned short指向char数组的指针并通过指针索引(每两个字节)进行迭代。

编译器通常会告诉您这一点,但是您使用 C 风格的转换会阻止这种情况(因为 C 风格的转换会默默地失败)。

稍后编辑:您的代码还索引unsigned short*最多str.length()元素,但是(short大于char)您的数组仅包含str.length() / 2 unsigned short可索引元素。

在某些机器上运行该代码可能会导致核心转储。

于 2012-12-11T13:10:26.913 回答
2

问题是您使用的是unsigned short指针,因此每个指针都会按字节++i前进。sizeof(unsigned short)如果在您的平台上sizeof(unsigned short)==2,很可能,第一个版本会跳过所有其他字符。

于 2012-12-11T13:09:35.147 回答
1

wstring 以两个字节格式存储原始数据,而 string 以一个字节或简单的 char 格式存储原始数据。在您执行 (unsigned short *)str.c_str() 的那一刻,您注定要跳两次而不是一次。在访问 str 的原始数据时,您必须使用 char* (根据我的经验,即使 unsigned char* 也会导致问题)。所以正确的做法是

const char *vtemp = str.c_str(); 
于 2012-12-11T13:15:48.380 回答
1

char 是一个字节,我不明白你为什么将对 c_str() 的调用转换为 an unsigned short*,对于一个:返回值不是unsigned(可能适用于某些平台,取决于编译器如何实现它)和二,为什么不暂时存储它返回的内容并用强制转换打印出来(查看它代表的数字)?

它“跳过”的原因是因为正如我所说的 std::string 和 std::wstring 定义如下:

std::string 的定义: typedef std::basic_string<char> std::string;

std::wstring 的定义: typedef std::basic_string<wchar_t> std::wstring;

如您所见,它们不是用无符号说明符定义的。对于 std::string,c_str() 返回 a const char*,对于 std::wstring,c_str() 返回 a const wchar_t*

因此,试试这个:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    std::string str = "mystring";
    const char* vtemp = str.c_str();
    for(int i=0; i<str.length(); ++i)
    {
        cout << (int)vtemp[i] << " ";
    }
    cout << endl;


    wstring wstr(str.length(), L' ');
    std::copy(str.begin(), str.end(), wstr.begin());


    const wchar_t* wtemp = wstr.c_str();

    for(int i=0; i<wstr.length(); ++i)
    {
       cout << (int)wtemp[i] << " ";
    }
    cout << endl;
}
于 2012-12-11T13:19:33.020 回答
0
unsigned short* vtemp = (unsigned short*)str.c_str();

用。。。来代替:

unsigned char* vtemp = (unsigned char*)str.c_str();
于 2012-12-11T13:10:27.240 回答