2008-10-19 5 views
48

J'ai lu la documentation sur WideCharToMultiByte, mais je suis bloqué sur ce paramètre:Comment utilisez-vous correctement WideCharToMultiByte

lpMultiByteStr 
[out] Pointer to a buffer that receives the converted string. 

Je ne suis pas tout à fait sûr comment initialiser correctement la variable et le nourrir en la fonction

+15

Y a-t-il une raison pour laquelle vous semblez poser des questions mais n'accepter aucune réponse? C'est généralement une bonne pratique sur ces sites de récompenser les bonnes réponses avec des commentaires en reconnaissance du temps que les gens investissent dans la réponse à votre question. Vous avez quelques très bonnes réponses ci-dessous ... (nudge) –

Répondre

16

Vous utilisez le paramètre lpMultiByteStr [out] en créant un nouveau tableau char. Vous passez ensuite ce tableau char pour le remplir. Vous avez seulement besoin d'initialiser la longueur de la chaîne + 1 afin que vous puissiez avoir une chaîne terminée par zéro après la conversion.

Voici quelques fonctions utiles pour vous, elles montrent l'utilisation de tous les paramètres.

#include <string> 

std::string wstrtostr(const std::wstring &wstr) 
{ 
    // Convert a Unicode string to an ASCII string 
    std::string strTo; 
    char *szTo = new char[wstr.length() + 1]; 
    szTo[wstr.size()] = '\0'; 
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, szTo, (int)wstr.length(), NULL, NULL); 
    strTo = szTo; 
    delete[] szTo; 
    return strTo; 
} 

std::wstring strtowstr(const std::string &str) 
{ 
    // Convert an ASCII string to a Unicode String 
    std::wstring wstrTo; 
    wchar_t *wszTo = new wchar_t[str.length() + 1]; 
    wszTo[str.size()] = L'\0'; 
    MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, wszTo, (int)str.length()); 
    wstrTo = wszTo; 
    delete[] wszTo; 
    return wstrTo; 
} 

-

Chaque fois que dans la documentation quand vous voyez qu'il a un paramètre qui est un pointeur sur un type, et ils vous diront qu'il est une variable, vous voulez créer ce type, puis passez-y un pointeur. La fonction utilisera ce pointeur pour remplir votre variable.

Alors vous pouvez mieux comprendre cela:

//pX is an out parameter, it fills your variable with 10. 
void fillXWith10(int *pX) 
{ 
    *pX = 10; 
} 

int main(int argc, char ** argv) 
{ 
    int X; 
    fillXWith10(&X); 
    return 0; 
} 
+4

Le code doit prendre en compte le fait que le nombre d'octets requis dans la chaîne char multibyte peut être supérieur au nombre de caractères dans la chaîne de caractères large. Un seul caractère large peut entraîner deux octets ou plus dans la chaîne de caractères multi-octets, en fonction des codages impliqués. –

+0

Pouvez-vous me donner un exemple? –

+0

Les charactes asiatiques me viennent à l'esprit, mais cela dépend vraiment de la page de code utilisée pour la conversion. Dans votre exemple, ce ne serait probablement pas un problème car tout caractère non-ANSI serait remplacé par un point d'interrogation. –

32

Élaborant sur le answer fourni par Brian R. Bondy: Voici un exemple qui montre pourquoi vous ne pouvez pas dimensionner simplement la mémoire tampon de sortie au nombre de caractères larges dans la chaîne de source:

#include <windows.h> 
#include <stdio.h> 
#include <wchar.h> 
#include <string.h> 

/* string consisting of several Asian characters */ 
wchar_t wcsString[] = L"\u9580\u961c\u9640\u963f\u963b\u9644"; 

int main() 
{ 

    size_t wcsChars = wcslen(wcsString); 

    size_t sizeRequired = WideCharToMultiByte(950, 0, wcsString, -1, 
               NULL, 0, NULL, NULL); 

    printf("Wide chars in wcsString: %u\n", wcsChars); 
    printf("Bytes required for CP950 encoding (excluding NUL terminator): %u\n", 
      sizeRequired-1); 

    sizeRequired = WideCharToMultiByte(CP_UTF8, 0, wcsString, -1, 
             NULL, 0, NULL, NULL); 
    printf("Bytes required for UTF8 encoding (excluding NUL terminator): %u\n", 
      sizeRequired-1); 
} 

Et la sortie:

Wide chars in wcsString: 6 
Bytes required for CP950 encoding (excluding NUL terminator): 12 
Bytes required for UTF8 encoding (excluding NUL terminator): 18 
+0

Un excellent exemple d'un aspect important et souvent négligé de la conversion de codepage/encodage! –

+0

-1 L'OP demande de l'aide avec le paramètre lpMultiByteStr. Cette réponse ne répond pas au PO, c'est une tangente à une autre réponse affichée. –

+2

@ Error454: Ils n'avaient pas de commentaires en 2008. Il suffit de le signaler. – Ryan

95

Voici quelques fonctions (basées sur l'exemple de Brian Bondy) qui utilisent WideCharToMultiByte et MultiByteToWideChar pour convertir entre std :: wstring et std :: string en utilisant utf8 pour ne perdre aucune donnée.

// Convert a wide Unicode string to an UTF8 string 
std::string utf8_encode(const std::wstring &wstr) 
{ 
    if(wstr.empty()) return std::string(); 
    int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); 
    std::string strTo(size_needed, 0); 
    WideCharToMultiByte     (CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL); 
    return strTo; 
} 

// Convert an UTF8 string to a wide Unicode String 
std::wstring utf8_decode(const std::string &str) 
{ 
    if(str.empty()) return std::wstring(); 
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0); 
    std::wstring wstrTo(size_needed, 0); 
    MultiByteToWideChar     (CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed); 
    return wstrTo; 
} 
+4

Il convient de noter qu'avant std :: string et std :: wstring ne sont pas garantis avoir leur mémoire contiguë. –

+1

Je doute sérieusement qu'il y ait jamais eu une implémentation de stl disponible dans le commerce qui n'ait pas de vecteurs contigus. Le fait que la mémoire contiguë n'était pas requise dans la première spécification C++ était un oubli: http://herbsutter.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/ – tfinniga

+1

@ tfinniga Le commentaire précédent concernait ** les chaînes **, pas les vecteurs. Les chaînes n'étaient pas garanties contiguës en C++ 98 (pas le résultat de la référence de Sutter), bien que toutes les implémentations du monde réel [les rendent contiguës] (http://stackoverflow.com/questions/1986966/does- s0-point-to-contiguous-caractères-in-a-stdstring). – user4815162342

Questions connexes