CStringと:: std :: string :: std :: wstringを相互に変換する方法は?
質問
CString
は非常に便利ですが、std::string
はSTLコンテナとより互換性があります。
hash_map
を使用しています。ただし、wstring
はキーとしてstd::wstring
をサポートしていないため、<=>を<=>に変換します。
<=>ハッシュ関数の作成には時間がかかるようです。
CString -----> std::string
これを行うにはどうすればよいですか
std::string -----> CString:
inline CString toCString(std::string const& str)
{
return CString(str.c_str());
}
そうですか
編集:
その他の質問:
<=>、<=>を相互に変換するにはどうすればよいですか?
//wstring -> CString,
std::wstring src;
CString result(src.c_str());
//CString->wstring.
CString src;
::std::wstring des(src.GetString());
何かの問題はありますか?
<=>、<=>を相互に変換するにはどうすればよいですか?
解決
CodeGuru によると:
CString
からstd::string
:
CString cs("Hello");
std::string s((LPCTSTR)cs);
しかし: LPCTSTR
は常にLPSTR
から構築できるとは限りません。つまり、UNICODEビルドではコードが失敗します。
LPCSTR
はCT2CA
/ CStringT
からのみ構築できるため、VC ++ 7.x以上を使用するプログラマーは、char*
などの変換クラスを媒介として利用できます。
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);
wchar_t*
to LPWSTR
:( Visual StudioのCString FAQから。 .. )
std::string s("Hello");
CString cs(s.c_str());
CStringA
は、文字列またはワイド文字列の両方から構成できます。つまり、wchar_t
(つまりCStringW
)から、またはTCHAR
(char
)から変換できます。
つまり、NUL
のchar-specialization、つまり<=>、<=>-specilization <=>、および<=>-specialization <=>は、<=>またはwide-文字、 null終了(ここではnull終了が非常に重要です)文字列ソース。
Althoug IInspectable は、<!> quot; null-termination <!> quot;を修正します。コメントの :
NUL終了は不要です。
<=>には、明示的な長さの引数を取る変換コンストラクターがあります。これは、<=>文字が埋め込まれた<=>オブジェクトから<=>オブジェクトを構築できることも意味します。
他のヒント
std::basic_string<TCHAR>
の代わりにstd::string
を使用することで解決し、キャラクター設定に関係なく正常に動作するはずです。
長さが指定されている変換を使用して、CString
をstd::string
に変換する方が効率的です。
CString someStr("Hello how are you");
std::string std(somStr, someStr.GetLength());
タイトループでは、これによりパフォーマンスが大幅に向上します。
もっと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);
}
(VS2012以降...および少なくともVS2017 v15.8.1まで)
MFCプロジェクトであるため<!> amp; 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
これは、彼が解決策を提供した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);
これは正常に動作します:
//Convert CString to std::string
inline std::string to_string(const CString& cst)
{
return CT2A(cst.GetString());
}
この投稿から( Mark Ransom ありがとう)
これをテストし、正常に動作します。
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;
}
私のために働く:
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();
}
他のすべての答えは、結果を変数に保存するのではなく、その場でCString
を変換することで、私が探していたものに完全には対応していませんでした。
ソリューションは上記と似ていますが、名前のないオブジェクトをインスタンス化するためにもう1ステップが必要です。例で説明しています。ここにstd::string
を必要とする関数がありますが、<=>があります。
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;
}
<=>があるときに呼び出す方法
std::string firstName = "First";
CString lastName = _T("Last");
writeLog( firstName + ", " + std::string( CT2A( lastName ) ) );
最後の行は直接型キャストではありませんが、名前のない<=>オブジェクトを作成し、コンストラクターを介して<=>を提供していることに注意してください。
何かの問題はありますか?
いくつかの問題があります:
-
CString
は、 CStringT 。文字タイプを記述する BaseType に応じて、2つの具体的な特殊化があります:CStringA
(char
を使用)およびCStringW
(wchar_t
を使用)。 - Windowsの
_UNICODE
は、UTF-16でエンコードされたコードユニットの格納に広く使用されていますが、std::string
の使用はあいまいです。後者は一般にANSIエンコード文字を保存しますが、ASCII、UTF-8、またはバイナリデータも保存できます。 -
std::wstring
(<=>プリプロセッサシンボルによって制御される)の文字エンコード(または文字タイプ)がわからないため、質問が曖昧になります。また、必要な<=>の文字エンコーディングもわかりません。 - UnicodeとANSI間の変換は本質的に損失があります。ANSIエンコードはUnicode文字セットのサブセットのみを表すことができます。
これらの問題に対処するために、<=>はUTF-16でエンコードされたコードユニットを格納し、<=>はUTF-8オクテットシーケンスを保持すると想定します。これは、ソースまたは宛先ドメインのサブセットにソリューションを制限することなく、ソースおよび宛先文字列が同じ情報を保持することを保証するために行うことができる唯一の合理的な選択です。
次の実装では、<=> / <=>と<=> / <=>のマッピングを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() };
}
CT2CA を使用できます
CString datasetPath;
CT2CA st(datasetPath);
string dataset(st);
他の文字列タイプ間で簡単に変換したい場合は、おそらく _bstr_t
クラスの方が適切ですか? char
、wchar_t
、およびBSTR
間の会話をサポートしています。
興味深いアプローチの1つは、CString
コンストラクター内でCStringA
をstring
にキャストすることです。 std::string s((LPCTSTR)cs);
とは異なり、これは_UNICODE
が定義されていても機能します。ただし、その場合、UnicodeからANSIへの変換が実行されるため、ASCII文字セットを超えるより高いUnicode値に対しては安全ではありません。このような変換は、_CSTRING_DISABLE_NARROW_WIDE_CONVERSION
プリプロセッサの定義に従います。 https://msdn.microsoft.com/en-us/library/5bzxfsea。 aspx
CString s1("SomeString");
string s2((CStringA)s1);