2008-10-19 20 views
48

He leído la documentación sobre WideCharToMultiByte, pero estoy atascado en este parámetro:¿Cómo se utiliza adecuadamente WideCharToMultiByte

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

No estoy muy seguro de cómo inicializar correctamente la variable y se alimentan en la función

+15

¿Hay alguna razón por la que parezca que hace preguntas pero no acepta respuestas? Por lo general, es una buena práctica en estos sitios recompensar las buenas respuestas con comentarios en reconocimiento por el tiempo que las personas invierten en responder su pregunta. A continuación encontrará algunas respuestas muy buenas ... (empuje) –

Respuesta

16

Utiliza el parámetro lpMultiByteStr [out] creando una nueva matriz de caracteres. A continuación, pasa esta matriz de caracteres para que se llene. Solo necesita inicializar la longitud de la cadena + 1 para que pueda tener una cadena con terminación nula después de la conversión.

Aquí hay un par de útiles funciones de ayuda para usted, que muestran el uso de todos los parámetros.

#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; 
} 

-

en cualquier momento en la documentación cuando se ve que tiene un parámetro que es un puntero a un tipo, y ellos dirán que es una variable de salida, tendrá que crear ese tipo, y luego pasa un puntero a él. La función usará ese puntero para llenar su variable.

para que pueda entender esto mejor:

//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

El código debe tener en cuenta que el número de bytes requerido en la cadena de caracteres multibyte puede ser mayor que el número de caracteres en la cadena de caracteres anchos. Un único carácter ancho puede dar como resultado 2 o más bytes en la cadena de caracteres multibyte, dependiendo de las codificaciones involucradas. –

+0

¿Me puede dar un ejemplo? –

+0

Los caracteres asiáticos vienen a la mente como un ejemplo, pero realmente depende de la página de códigos que se usa para la conversión. En su ejemplo, probablemente no sería un problema, porque cualquier carácter que no pertenezca a ANSI se reemplazará por un signo de interrogación. –

32

Abundando en la answer proporcionado por Brian R. Bondy: He aquí un ejemplo que muestra por qué no puede simplemente el tamaño del búfer de salida para el número de caracteres anchos en la cadena de origen:

#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); 
} 

Y la salida:

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 excelente ejemplo de un aspecto importante y a menudo descuidado de la conversión de codificación/página de códigos! –

+0

-1 El OP solicita ayuda con el parámetro lpMultiByteStr. Esta respuesta no responde al OP, es una tangente a otra respuesta publicada. –

+2

@ Error454: No tuvieron comentarios en 2008. Solo márquelo. – Ryan

95

Aquí hay un par de funciones (basadas en el ejemplo de Brian Bondy) que usan WideCharToMultiByte y MultiByteToWideChar para convertir entre std :: wstring y std :: string usando utf8 para no perder ningún dato.

// 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

Debe tenerse en cuenta que antes de C++ 11 std :: string y std :: wstring no estaban garantizados tener su memoria contigua. –

+1

Tengo serias dudas de que alguna vez haya existido una implementación stl disponible comercialmente que no tenga vectores contiguos. El hecho de que no se requiriera memoria contigua en la primera especificación de C++ fue un descuido: http://herbsutter.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/ – tfinniga

+1

@ tfinniga El comentario anterior fue sobre ** cadenas **, no sobre vectores. No se garantiza que las cadenas sean contiguas en C++ 98 (no es el resultado del referido por Sutter), aunque todas las implementaciones del mundo real [las hacen contiguas] (http://stackoverflow.com/questions/1986966/does- s0-point-to-contiguous-characters-in-a-stdstring). – user4815162342

Cuestiones relacionadas