1

CストリングとワイドCストリングについて少し混乱しています。この質問のために、私がMicrosoft Visual Studio2010Professionalを使用していると仮定します。私の情報が間違っている場合はお知らせください。

名前を格納するために使用されるconstwchar_t*メンバーを持つ構造体があります。

struct A
{
    const wchar_t* name;
};

オブジェクト「a」に名前を付けると、次のようになります。

int main()
{
    A a;

    const wchar_t* w_name = L"Tom";
    a.name = w_name;

    return 0;
}

これは、w_nameが指すメモリアドレスをa.nameにコピーするだけです。現在、w_nameとa.nameはどちらも、メモリ内の同じアドレスを指すワイド文字ポインタです。

私が正しければ、私はこのような状況をどうしたらいいのだろうと思っています。tinyxml2を使用してXML属性からC文字列を読み込んでいます。

tinyxml2::XMLElement* pElement;
// ...
const char* name = pElement->Attribute("name");

C文字列を取得したら、次のようにワイド文字列に変換します。

size_t newsize = strlen(name) + 1;
wchar_t * wcName = new wchar_t[newsize];
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, wcName, newsize, name, _TRUNCATE);

a.name = wcName;

delete[] wcName;

私がこれまでのところ正しければ、次の行があります。

 a.name = wcName;

配列wcNameの最初の文字のメモリアドレスをa.nameにコピーしているだけです。ただし、このポインタを割り当てた直後にwcNameを削除しているため、ガベージを指すようになります。

C文字列をワイド文字のC文字列に変換してから、それをa.nameに割り当てるにはどうすればよいですか?

4

3 に答える 3

3

最も簡単な方法は、name変数にメモリの管理を任せることです。これは、次のように宣言することで簡単に実行できます。

std::wstring name;

これらの人には、独立したコンテンツとオブジェクトの突然変異の概念がありません。つまり、個々のキャラクターconstを実際に作成することはできず、オブジェクト全体を作成するconstと、それが割り当てられなくなります。

于 2012-11-15T20:04:17.437 に答える
1

追加の一時変換バッファーの割り当てと破棄に依存せずに、を使用しながらこれを行うことができます。std::wstringヒープの断片化や制限されたシステム (別名 Windows Phone) について明らかに懸念している場合を除き、それほど重要ではありません。フロント側に少し設定が必要です。標準ライブラリにメモリを管理させます (ちょっとしたコツで)。

class A
{
   ...
   std::wstring a;
};


// Convert the string (I'm assuming it is UTF8) to wide char
int wlen = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, NULL);
if (wlen > 0)
{
    // reserve space. std::wstring gives us the terminator slot
    // for free, so don't include that. MB2WC above returns the
    // length *including* the terminator.
    a.resize(wlen-1);
    MultiByteToWideChar(CP_UTF8, 0, name, -1, &a[0], wlen);
}
else
{   // no conversion available/possible.
    a.clear();
}

完全な補足として、TinyXML を構築して、標準ライブラリではなく を使用することができstd::stringますchar *。これは、ここではあまり役に立ちませんが、後で大量の呼び出しを節約できる可能性がありますstrlen()

于 2012-11-15T21:02:21.587 に答える
0

あなたが正しく述べたようa.nameに、割り当てられた文字列ストレージを想定していない単なるポインターです。newまたは静的/スコープ配列を使用して手動で管理する必要があります。

これらの退屈なものを取り除くには、使用可能な文字列クラスの 1 つを使用するだけです: CStringWATL (使いやすいが MS 固有) またはstd::wstringSTL (C++ 標準ですが、から変換するのはそれほど簡単ではありませんchar*) から:

#include <atlstr.h>

// Conversion ANSI -> Wide is automatic
const CStringW name(pElement->Attribute("name"));    

残念ながら、 でのstd::wstring使用char*はそれほど簡単ではありません。ここで変換関数を参照してください: C++ (Unicode) で std::string を LPCWSTR に変換する方法

于 2012-11-15T20:21:57.270 に答える