Ich möchte eine normale string
in eine wstring
konvertieren. Hierfür versuche ich die Windows-API-Funktion MultiByteToWideChar
zu verwenden. Aber bei mir funktioniert es nicht.
Folgendes habe ich getan:
string x = "This is c++ not Java";
wstring Wstring;
MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , x.size() , &Wstring , 0 );
Die letzte Zeile erzeugt den Compilerfehler:
'MultiByteToWideChar' : cannot convert parameter 5 from 'std::wstring *' to 'LPWSTR'
Wie behebe ich diesen Fehler?
Und was sollte der Wert des Arguments cchWideChar
sein? Ist 0 in Ordnung?
Sie müssen zweimal MultiByteToWideChar
aufrufen:
Der erste Aufruf von MultiByteToWideChar
wird verwendet, um die Puffergröße zu ermitteln, die Sie für den Wide-String benötigen. Schauen Sie sich Microsoft-Dokumentation an. Es sagt aus:
Wenn die Funktion erfolgreich ist und cchWideChar 0 ist, ist der Rückgabewert die erforderliche Größe (in Zeichen) für den Puffer, der durch lpWideCharStr angegeben wird.
Um MultiByteToWideChar
die erforderliche Größe zu geben, übergeben Sie 0 als Wert des letzten Parameters cchWideChar
. Sie sollten auch NULL
als davor übergeben, lpWideCharStr
.
Erhalten Sie einen Nicht-Konstantenpuffer, der groß genug ist, um die breite Zeichenfolge aufzunehmen, und verwenden Sie dabei die Puffergröße aus dem vorherigen Schritt. Übergeben Sie diesen Puffer an einen anderen Aufruf von MultiByteToWideChar
. Dieses Mal sollte das letzte Argument die tatsächliche Größe des Puffers sein, nicht 0.
Ein skizzenhaftes Beispiel:
int wchars_num = MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , -1, NULL , 0 );
wchar_t* wstr = new wchar_t[wchars_num];
MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , -1, wstr , wchars_num );
// do whatever with wstr
delete[] wstr;
Beachten Sie auch die Verwendung von -1 als cbMultiByte
-Argument. Dadurch wird die resultierende Zeichenfolge nullterminiert, sodass Sie nicht mehr mit der Zeichenkette umgehen müssen.
Zweite Frage dazu heute morgen!
WideCharToMultiByte () und MultiByteToWideChar () sind sehr schwer zu verwenden. Für jede Konvertierung sind zwei Aufrufe der Routinen erforderlich, und Sie müssen nach dem Zuweisen/Freigeben von Speicher und nach der korrekten Beendigung der Zeichenfolgen darauf achten. Du brauchst einen Wrapper!
Ich habe einen praktischen C++ - Wrapper in meinem Blog, hier , den Sie gerne verwenden.
Hier ist die andere Frage heute morgen
Sie können diese Lösung unten ausprobieren. Ich habe getestet, es funktioniert, erkennt Sonderzeichen (Beispiel: º ä ç á) und funktioniert unter Windows XP, Windows 2000 mit SP4 und höher, Windows 7, 8, 8.1 und 10. Verwenden statt std::wstring
statt new wchar_t
/delete
, reduzieren wir Probleme mit Leckressourcen, Überlaufpuffer und beschädigter Heap.
dwFlags
wurde auf MB_ERR_INVALID_CHARS
gesetzt, um unter Windows 2000 mit SP4 und höher, Windows XP, zu funktionieren. Wenn dieses Flag nicht gesetzt ist, löscht die Funktion unzulässige Codepunkte.
std::wstring ConvertStringToWstring(const std::string &str)
{
if (str.empty())
{
return std::wstring();
}
int num_chars = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, str.c_str(), str.length(), NULL, 0);
std::wstring wstrTo;
if (num_chars)
{
wstrTo.resize(num_chars);
if (MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, str.c_str(), str.length(), &wstrTo[0], num_chars))
{
return wstrTo;
}
}
return std::wstring();
}
Die Funktion kann keinen Zeiger auf eine C++ - Zeichenfolge aufnehmen. Es wird ein Zeiger auf einen Puffer mit breiten Zeichen von ausreichender Größe erwartet - Sie müssen diesen Puffer selbst zuordnen.
string x = "This is c++ not Java";
wstring Wstring;
Wstring.resize(x.size());
int c = MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , x.size() , &Wstring[0], 0 );