web-dev-qa-db-de.com

Wie verwende ich MultiByteToWideChar?

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?

16
Suhail Gupta

Sie müssen zweimal MultiByteToWideChar aufrufen:

  1. 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.

  2. 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.

32
eran

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

1
ravenspoint

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();
}
0
Nix

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 ); 
0
Puppy