Como você usar corretamente WideCharToMultiByte

votos
48

Eu li a documentação sobre WideCharToMultiByte , mas eu estou preso neste parâmetro:

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

Eu não estou muito certo como ao inicializar corretamente a variável e alimentá-lo para a função

Publicado 19/10/2008 em 04:33
fonte usuário
Em outras línguas...                            


3 respostas

votos
99

Aqui está um par de funções (com base no exemplo de Brian Bondy) que usam WideCharToMultiByte e MultiByteToWideChar para converter entre std :: wstring e std :: string usando utf8 para não perder quaisquer dados.

// 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;
}
Respondeu 22/10/2010 em 18:59
fonte usuário

votos
32

Elaborando sobre a resposta fornecida por Brian R. Bondy: Aqui está um exemplo que mostra que você não pode simplesmente dimensionar o buffer de saída para o número de caracteres largos na cadeia de origem:

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

E a saída:

Wide chars in wcsString: 6
Bytes required for CP950 encoding (excluding NUL terminator): 12
Bytes required for UTF8 encoding (excluding NUL terminator): 18
Respondeu 19/10/2008 em 20:52
fonte usuário

votos
16

Você usar o parâmetro lpMultiByteStr [out] criando uma nova matriz de char. Você, então, passar essa matriz de char para obtê-lo preenchido. Você só precisa inicializar o comprimento da corda + 1 para que você pode ter um nulo string terminada após a conversão.

Aqui estão um par de funções auxiliares úteis para você, eles mostram o uso de todos os 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;
}

-

A qualquer hora na documentação quando você vê que tem um parâmetro que é um ponteiro para um tipo, e eles dizer-lhe que é uma variável fora, você vai querer criar esse tipo, e em seguida, passar um ponteiro para ele. A função vai usar esse ponteiro para preencher a variável.

Assim você pode entender isso melhor:

//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;
}
Respondeu 19/10/2008 em 04:41
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more