6

C++ で小さな Win32 アプリを開発しています。私はずっと前に C++ の基礎を勉強していたので、C++ の文字列のせいで完全に混乱してしまいました。なし、WCHARまたはとTCHARしかcharありませんでしStringた。少し調査した結果、使用しないことにしましたTCHAR

私の問題は非常に単純だと思いますが、C++ で文字列を操作する明確なガイドが見つかりません。ここ数年の PHP コーディングの影響を受けて、文字列操作で単純なものを期待していましたが、間違っていました!

簡単に言えば、新しいデータを文字列に入れるだけです。

    WCHAR* cs = L"\0";
    swprintf( cs, "NEW DATA" );

これは私の最初の試みでした。アプリをデバッグするときに、swprintf が最初の 2 文字だけを cs 変数に入れることを調査しました。私はこの方法で問題を解決しました:

    WCHAR cs[1000];
    swprintf( cs, "NEW DATA" );

しかし、私の場合、新しいデータは定数値ではなく、別の変数であり、1000 文字よりも長くなる可能性があるため、通常、このトリックは失敗する可能性があります。そして私のコードは次のようになります:

    WCHAR cs[1000];
    WCHAR* nd1;
    WCHAR* nd2;
    wcscpy(nd1, L"Some value");
    wcscpy(nd2, L"Another value"); // Actually these vars stores the path for user selected folder
    swprintf( cs, "The paths are %s and %s", nd1, nd2);

この場合、nd1 と nd2 の合計文字数が 1000 文字を超える可能性があるため、重要なデータが失われます。

問題は、このように宣言された WCHAR 文字列に必要なすべてのデータをWCHAR* wchar_var;、何も失うことなくコピーするにはどうすればよいかということです。

PS 私はロシア人なので、質問が不明確かもしれません。私の問題をより明確かつ複雑に説明しようと思います。

4

3 に答える 3

7

最新の Windows プログラミングでは、無視TCHARして代わりにwchar_t( WCHAR) と Unicode UTF-16 を使用しても問題ありません。

(は、単一のコード ベースを持ち、ANSI/MBCS と Unicode の両方のビルドを作成して、や などTCHARのプリプロセッサ スイッチを変更したかった過去のモデルです。)_UNICODEUNICODE

いずれにせよ、C++ と便利な文字列クラスを使用してコードを簡素化する必要があります。(VS2005以降のデフォルトであるUnicodeビルドにATL::CString対応CStringW)、またはSTLのstd::wstring.

を使用するCStringと、次のことができます。

CString str1 = L"Some value";
CString str2 = L"Another value";
CString cs;
cs.Format(L"The paths are %s and %s", str1.GetString(), str2.GetString());

CStringまた、文字列を連結するための適切なオーバーロードも提供しoperator+ます (したがって、結果の文字列の合計長を計算したり、宛先文字列にバッファーを動的に割り当てたり、既存のバッファー サイズを確認したり、 , を呼び出しwcscpyたりwcscat、バッファーを解放することを忘れないでください)など)

への暗黙的な変換演算子を提供するため、 ( ) パラメータをCString期待してのインスタンスを Win32 API に渡すだけで済みます。const wchar_t*LPCWSTR/PCWSTRCStringconst wchar_t*

于 2012-11-13T11:58:03.717 に答える
2

を使用しているWCHAR*場合、ポインターはあるが有効なものを指していないため、未定義の動作を呼び出しています。結果の文字列の長さを調べ、文字列に動的にスペースを割り当てる必要があります。例えば:

WCHAR* cs;
WCHAR* nd1;
WCHAR* nd2;

nd1 = new WCHAR[lstrlen(L"Some value") + 1]; // +1 for the null terminator
nd2 = new WCHAR[lstrlen(L"Another value") + 1];
cs = new WCHAR[lstrlen(L"The paths are  and ") + lstrlen(nd1) + lstrlen(nd2) + 1];

wcscpy(nd1, L"Some value");
wcscpy(nd2, L"Another value"); // Actually these vars stores the path for user selected folder
swprintf( cs, L"The paths are %s and %s", nd1, nd2);

delete[] nd1;
delete[] nd2;
delete[] cs;

しかし、これは非常に見苦しく、エラーが発生しやすいものです。前述のように、std::wstring代わりに次のようなものを使用する必要があります。

std::wstring cs;
std::wstring nd1;
std::wstring nd2;

nd1 = L"Some value";
nd2 = L"Another value";
cs = std::wstring(L"The paths are ") + nd1 + L" and " + nd2;
于 2012-11-13T11:57:50.650 に答える
1

raw の代わりにATLCStringWクラスを使用することをお勧めしWCHARます。はるかに便利です。CString動的に割り当てられた C 文字列のラッパーです。各操作の後に文字列の長さと割り当てられたメモリバッファーを適切に管理するので、気にする必要はありません。

典型的な使用法:

#include <atlstr.h>

CStringW s;
s.Format(L"The paths are %s and %s", L"Some value", L"Another value");
const WCHAR* wstr = s.GetString(); // To pass to some API that need WCHAR

また

#include <atlstr.h>

CStringW s(L"The paths are ");
s += L"Some value";
s += L" and ";
s += L"Another value";
const WCHAR* wstr = s.GetString(); // To pass to some API that need WCHAR
于 2012-11-13T12:10:49.363 に答える