0

std::wstring が正常に動作しているときに std::string のバイト表現を出力しているときに、奇妙なエラーに直面しています。

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長さは2バイトです。char1バイトの長さです。unsigned short配列へのポインターを設定し、charポインターのインデックス付け(2バイトごと)によって反復します。

コンパイラは通常それを通知しますが、Cスタイルのキャストを使用するとそれが防止されます(Cスタイルのキャストはサイレントに失敗するため)。

後で編集:コードもunsigned short*最大str.length()要素にインデックスを付けますが、配列にはインデックス可能な要素のみが含まれます(shortより大きい)。charstr.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

unsigned short*char はバイトです。 c_str () への呼び出しを an にキャストする理由がわかりませんunsigned. 2 つ目は、返されたものを一時的に保存し、キャストで出力してみませんか (それが表す数値を確認するため)。

「スキップ」する理由は、私が言ったように、 std::string と std::wstring が次のように定義されているためです。

std::string の定義: typedef std::basic_string<char> std::string;

std::wstring の定義: typedef std::basic_string<wchar_t> std::wstring;

ご覧のとおり、これらは unsigned 指定子で定義されていません。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 に答える
1

wstring は生データを 2 バイト形式で保存しますが、string はそれを 1 バイトまたは単に char 形式で保存します。(unsigned short *)str.c_str() を実行した瞬間、1 つではなく 2 つのジャンプを行うことになります。str の生データにアクセスするときは、char* を使用する必要があります (私の経験では unsigned char* でも問題が発生する可能性があります)。したがって、行うべき正しいことは

const char *vtemp = str.c_str(); 
于 2012-12-11T13:15:48.380 に答える
0
unsigned short* vtemp = (unsigned short*)str.c_str();

と置換する:

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