web-dev-qa-db-fra.com

Comment utiliser MultiByteToWideChar?

Je veux convertir une string normale en une wstring. Pour cela, j'essaie d'utiliser la fonction API Windows MultiByteToWideChar . Mais ça ne marche pas pour moi.

Voici ce que j'ai fait:

string x = "This is c++ not Java";
wstring Wstring;
MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , x.size() , &Wstring , 0 ); 

La dernière ligne produit l'erreur du compilateur:

'MultiByteToWideChar' : cannot convert parameter 5 from 'std::wstring *' to 'LPWSTR'

Comment puis-je corriger cette erreur?

En outre, quelle devrait être la valeur de l'argument cchWideChar? Est-ce que 0 va bien?

16
Suhail Gupta

Vous devez appeler MultiByteToWideChar deux fois:

  1. Le premier appel à MultiByteToWideChar permet de rechercher la taille de la mémoire tampon dont vous avez besoin pour la chaîne large. Regardez la documentation de Microsoft ; il est dit:

    Si la fonction réussit et cchWideChar vaut 0, la valeur de retour est la taille requise, en caractères, pour la mémoire tampon indiquée par lpWideCharStr .

    Ainsi, pour que MultiByteToWideChar vous donne la taille requise, transmettez 0 comme valeur du dernier paramètre, cchWideChar. Vous devriez également passer NULL comme celui qui le précède, lpWideCharStr.

  2. Obtenez un tampon non-const suffisamment grand pour contenir la chaîne large, en utilisant la taille du tampon de l'étape précédente. Passez ce tampon à un autre appel à MultiByteToWideChar. Et cette fois, le dernier argument devrait être la taille réelle du tampon, pas 0.

Un exemple sommaire:

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;

Notez également l'utilisation de -1 comme argument cbMultiByte. Cela rendra la chaîne résultante terminée par un caractère null, vous évitant ainsi de les traiter.

32
eran

Deuxième question à ce sujet, ce matin!

WideCharToMultiByte () et MultiByteToWideChar () sont une douleur à utiliser. Chaque conversion nécessite deux appels aux routines et vous devez vous assurer que la chaîne est allouée/libérée et que les chaînes sont correctement terminées. Vous avez besoin d'un emballage!

J'ai un wrapper C++ pratique sur mon blog, ici , que vous êtes invités à utiliser.

Voici l'autre question ce matin

1
ravenspoint

Vous pouvez essayer cette solution ci-dessous. J'ai testé, cela fonctionne, détecte des caractères spéciaux (exemple: º ä ç á) et fonctionne sous Windows XP, Windows 2000 avec SP4 et versions ultérieures, Windows 7, 8, 8.1 et 10. Utilisation de std::wstring à la place de new wchar_t/delete , nous réduisons les problèmes liés aux fuites de ressources, au buffer de débordement et au tas corrompu.

dwFlags a été défini sur MB_ERR_INVALID_CHARS pour fonctionner sous Windows 2000 avec SP4 et versions ultérieures, Windows XP. Si cet indicateur n'est pas défini, la fonction supprime silencieusement les points de code illégaux.

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

La fonction ne peut pas prendre un pointeur sur une chaîne C++. Il attendra un pointeur sur un tampon de caractères larges de taille suffisante - vous devez l'allouer vous-même.

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