web-dev-qa-db-ja.com

CStringと:: std :: string :: std :: wstringを相互に変換する方法は?

CStringは非常に便利ですが、std::stringはSTLコンテナとより互換性があります。 hash_mapを使用しています。ただし、hash_mapCStringをキーとしてサポートしていないため、CStringstd::stringに変換します。

CStringハッシュ関数の作成には時間がかかるようです。

CString -----> std::string

これどうやってするの?

std::string -----> CString:

inline CString toCString(std::string const& str)
{
    return CString(str.c_str()); 
}

私は正しいですか?


編集:

その他の質問:

wstringCStringを相互に変換するにはどうすればよいですか?

//wstring -> CString,
std::wstring src;
CString result(src.c_str());
//CString->wstring. 
CString src;
::std::wstring des(src.GetString());

any問題はありますか?

std::wstringstd::stringを相互に変換するにはどうすればよいですか?

68
user25749

CodeGur によると:

CStringからstd::stringへ:

CString cs("Hello");
std::string s((LPCTSTR)cs);

BUT:std::stringは常にLPCTSTRから構築できるとは限りません。つまり、UNICODEビルドのコードは失敗します。

std::stringLPSTR/LPCSTRからのみ構築できるため、VC++ 7.x以上を使用するプログラマーは、CT2CAなどの変換クラスを仲介として使用できます。

CString cs ("Hello");
// Convert a TCHAR string to a LPCSTR
CT2CA pszConvertedAnsiString (cs);
// construct a std::string using the LPCSTR input
std::string strStd (pszConvertedAnsiString);

std::string to CString :(From Visual StudioのCString FAQ ...

std::string s("Hello");
CString cs(s.c_str());

CStringTは、文字またはワイド文字の両方の文字列から構築できます。つまり、char*(つまりLPSTR)またはwchar_t*LPWSTR)から変換できます。

つまり、(CStringTの)char-specialization、つまりCStringAwchar_t- specilization CStringW、およびTCHAR- specialization CStringは、charまたはワイド文字のいずれかから構築できます。 null終了(null終了はここで非常に重要です) 文字列ソース。
Althoug IInspectable 「ヌル終端」部分を修正 コメント内

NUL終端は不要です
CStringTには、明示的な長さの引数を取る変換コンストラクターがあります。これは、CStringT文字が埋め込まれたstd::stringオブジェクトからNULオブジェクトを構築できることも意味します。

85
VonC

std::basic_string<TCHAR>の代わりにstd::stringを使用することでそれを解決し、キャラクター設定に関係なく正常に動作するはずです。

34
OJ.

長さが指定されている変換を使用して、CStringstd::stringに変換する方が効率的です。

CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());

タイトループでは、これによりパフォーマンスが大幅に向上します。

5
Sal

もっとC++に似たものが必要な場合は、これを使用します。 Boostに依存しますが、それは単なる例外です。 STLとWideCharToMultiByte() Win32 API呼び出しのみに依存するように、それらを簡単に削除できます。

#include <string>
#include <vector>
#include <cassert>
#include <exception>

#include <boost/system/system_error.hpp>
#include <boost/integer_traits.hpp>

/**
 * Convert a Windows wide string to a UTF-8 (multi-byte) string.
 */
std::string WideStringToUtf8String(const std::wstring& wide)
{
    if (wide.size() > boost::integer_traits<int>::const_max)
        throw std::length_error(
            "Wide string cannot be more than INT_MAX characters long.");
    if (wide.size() == 0)
        return "";

    // Calculate necessary buffer size
    int len = ::WideCharToMultiByte(
        CP_UTF8, 0, wide.c_str(), static_cast<int>(wide.size()), 
        NULL, 0, NULL, NULL);

    // Perform actual conversion
    if (len > 0)
    {
        std::vector<char> buffer(len);
        len = ::WideCharToMultiByte(
            CP_UTF8, 0, wide.c_str(), static_cast<int>(wide.size()),
            &buffer[0], static_cast<int>(buffer.size()), NULL, NULL);
        if (len > 0)
        {
            assert(len == static_cast<int>(buffer.size()));
            return std::string(&buffer[0], buffer.size());
        }
    }

    throw boost::system::system_error(
        ::GetLastError(), boost::system::system_category);
}
4
thehouse

(VS2012以降...および少なくともVS2017 v15.8.1まで)

MFCプロジェクトであり、CStringはMFCクラスであるため、MSはテクニカルノート TN059:MFC MBCS/Unicode変換マクロの使用 および汎用変換マクロを提供します。

A2CW      (LPCSTR)  -> (LPCWSTR)  
A2W       (LPCSTR)  -> (LPWSTR)  
W2CA      (LPCWSTR) -> (LPCSTR)  
W2A       (LPCWSTR) -> (LPSTR)  

つかいます:

void Example() // ** UNICODE case **
{
    USES_CONVERSION; // (1)

    // CString to std::string / std::wstring
    CString strMfc{ "Test" }; // strMfc = L"Test"
    std::string strStd = W2A(strMfc); // ** Conversion Macro: strStd = "Test" **
    std::wstring wstrStd = strMfc.GetString(); // wsrStd = L"Test"

    // std::string to CString / std::wstring
    strStd = "Test 2";
    strMfc = strStd.c_str(); // strMfc = L"Test 2"
    wstrStd = A2W(strStd.c_str()); // ** Conversion Macro: wstrStd = L"Test 2" **

    // std::wstring to CString / std::string 
    wstrStd = L"Test 3";
    strMfc = wstrStd.c_str(); // strMfc = L"Test 3"
    strStd = W2A(wstrStd.c_str()); // ** Conversion Macro: strStd = "Test 3" **
}

-

脚注:

(1)変換マクロに一時的な長さを格納するスペースを確保するには、変換マクロを使用する各関数でこれを行う_convertというローカル変数を宣言する必要があります。これは、USES_CONVERSIONマクロを呼び出すことで実行されます。 VS2017 MFCコード(atlconv.h)では、次のようになります。

#ifndef _DEBUG
    #define USES_CONVERSION int _convert; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw; (_lpw); LPCSTR _lpa; (_lpa)
#else
    #define USES_CONVERSION int _convert = 0; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw = NULL; (_lpw); LPCSTR _lpa = NULL; (_lpa)
#endif
2
Amit G.

これは、彼が解決策を提供したSalの回答のフォローアップです。

CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());

これは、非典型的なC-Stringをstd :: stringに変換するときにも役立ちます

私のユースケースは、事前に割り当てられたchar配列(C-Stringなど)でしたが、NULで終了していません。 (つまりSHAダイジェスト)。上記の構文により、char配列のSHAダイジェストの長さを指定できるため、std :: stringが終端のNUL文字を探す必要があります。終端文字は、存在する場合と存在しない場合があります。

といった:

unsigned char hashResult[SHA_DIGEST_LENGTH];    
auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH);
1
Neil

この投稿から(ありがとう Mark Ransom

CStringを文字列に変換(VC6)

私はこれをテストしましたが、うまくいきます。

std::string Utils::CString2String(const CString& cString) 
{
    std::string strStd;

    for (int i = 0;  i < cString.GetLength();  ++i)
    {
        if (cString[i] <= 0x7f)
            strStd.append(1, static_cast<char>(cString[i]));
        else
            strStd.append(1, '?');
    }

    return strStd;
}
1
Pat. ANDRIA

これはうまくいきます:

//Convert CString to std::string
inline std::string to_string(const CString& cst)
{
    return CT2A(cst.GetString());
}
1
freeze

他のすべての答えは、結果を変数に保存するのではなく、その場でCStringを変換することで、私が探していたものにはまったく対応していませんでした。

解決方法は上記と似ていますが、名前のないオブジェクトをインスタンス化するためにもう1ステップが必要です。例で説明しています。ここにstd::stringを必要とする私の関数がありますが、CStringがあります。

void CStringsPlayDlg::writeLog(const std::string &text)
{
    std::string filename = "c:\\test\\test.txt";

    std::ofstream log_file(filename.c_str(), std::ios_base::out | std::ios_base::app);

    log_file << text << std::endl;
}

CStringがあるときに呼び出す方法は?

std::string firstName = "First";
CString lastName = _T("Last");

writeLog( firstName + ", " + std::string( CT2A( lastName ) ) );     

最後の行は直接型キャストではありませんが、名前のないstd::stringオブジェクトを作成し、そのコンストラクターを介してCStringを提供していることに注意してください。

0
zar

CT2CAを使用できます

CString datasetPath;
CT2CA st(datasetPath);
string dataset(st);
0
shawon

私のために働く:

std::wstring CStringToWString(const CString& s)
{
    std::string s2;
    s2 = std::string((LPCTSTR)s);
    return std::wstring(s2.begin(),s2.end());
}

CString WStringToCString(std::wstring s)
{
    std::string s2;
    s2 = std::string(s.begin(),s.end());
    return s2.c_str();
}
0
user5546107

何か問題はありますか?

いくつかの問題があります。

  • CStringは、 CStringT のテンプレート特化です。文字タイプを記述するBaseTypeに応じて、2つの具体的な特殊化があります:CStringAcharを使用)およびCStringWwchar_t)を使用します。
  • Windowsのwchar_tはUTF-16でエンコードされたコードユニットを格納するために広く使用されていますが、charを使用することはあいまいです。後者は一般にANSIエンコード文字を保存しますが、ASCII、UTF-8、またはバイナリデータを保存することもできます。
  • CString_UNICODEプリプロセッサシンボルによって制御される)の文字エンコード(または文字タイプ)がわからないため、質問が曖昧になります。また、std::stringの目的の文字エンコーディングもわかりません。
  • UnicodeとANSI間の変換は本質的に損失が大きく、ANSIエンコードはUnicode文字セットのサブセットのみを表すことができます。

これらの問題に対処するために、wchar_tはUTF-16でエンコードされたコードユニットを格納し、charはUTF-8オクテットシーケンスを保持すると想定します。これは、ソースドメインと宛先ドメインのサブセットにソリューションを制限することなく、ソース文字列と宛先文字列が同じ情報を保持するようにするための唯一の合理的な選択です。

次の実装は、CStringA/CStringWstd::wstring/std::stringマッピング間でUTF-8からUTF-16へ、またはその逆に変換します。

#include <string>
#include <atlconv.h>

std::string to_utf8(CStringW const& src_utf16)
{
    return { CW2A(src_utf16.GetString(), CP_UTF8).m_psz };
}

std::wstring to_utf16(CStringA const& src_utf8)
{
    return { CA2W(src_utf8.GetString(), CP_UTF8).m_psz };
}

残りの2つの関数は、MFC文字列からC++文字列オブジェクトを構築し、エンコードは変更しません。以前の関数は埋め込まれたNUL文字に対応できないが、これらの関数はそれに対して耐性があることに注意してください。

#include <string>
#include <atlconv.h>

std::string to_std_string(CStringA const& src)
{
    return { src.GetString(), src.GetString() + src.GetLength() };
}

std::wstring to_std_wstring(CStringW const& src)
{
    return { src.GetString(), src.GetString() + src.GetLength() };
}
0
IInspectable