web-dev-qa-db-fra.com

Comment convertir char * en wchar_t *?

J'ai essayé d'implémenter une fonction comme celle-ci, mais malheureusement cela ne fonctionne pas:

const wchar_t *GetWC(const char *c)
{
    const size_t cSize = strlen(c)+1;
    wchar_t wc[cSize];
    mbstowcs (wc, c, cSize);

    return wc;
}

Mon objectif principal ici est de pouvoir intégrer des chaînes de caractères normales dans une application Unicode. Tous les conseils que vous pouvez offrir sont grandement appréciés.

48
AutoBotAM

Utilisez un std::wstring Au lieu d’un tableau de longueur variable C99. La norme actuelle garantit un tampon contigu pour std::basic_string. Par exemple.,

std::wstring wc( cSize, L'#' );
mbstowcs( &wc[0], c, cSize );

C++ ne prend pas en charge les tableaux de longueur variable C99. Par conséquent, si vous compiliez votre code en tant que C++ pur, il ne serait même pas compilé.

Avec ce changement, votre type de retour de fonction devrait également être std::wstring.

N'oubliez pas de définir les paramètres régionaux pertinents dans main.

Par exemple, setlocale( LC_ALL, "" ).

Vive & hth.,

31

Dans votre exemple, wc est une variable locale qui sera désallouée à la fin de l'appel de la fonction. Cela vous met dans un territoire de comportement indéfini.

La solution simple est la suivante:

const wchar_t *GetWC(const char *c)
{
    const size_t cSize = strlen(c)+1;
    wchar_t* wc = new wchar_t[cSize];
    mbstowcs (wc, c, cSize);

    return wc;
}

Notez que le code d'appel devra alors libérer la mémoire, sinon vous aurez une fuite de mémoire.

36
Andrew Shepherd
const char* text_char = "example of mbstowcs";
size_t length = strlen(text_char );

Exemple d'utilisation "mbstowcs"

std::wstring text_wchar(length, L'#');

//#pragma warning (disable : 4996)
// Or add to the preprocessor: _CRT_SECURE_NO_WARNINGS
mbstowcs(&text_wchar[0], text_char , length);

Exemple d'utilisation "mbstowcs_s"

Microsoft suggère d'utiliser "mbstowcs_s" au lieu de "mbstowcs".

Liens:

exemple Mbstowcs

mbstowcs_s, _mbstowcs_s_l

wchar_t text_wchar[30];

mbstowcs_s(&length, text_wchar, text_char, length);
4
Maks

Vous retournez l'adresse d'une variable locale allouée sur la pile. Lorsque votre fonction revient, le stockage de toutes les variables locales (telles que wc) est libéré et est susceptible d'être immédiatement écrasé par quelque chose d'autre.

Pour résoudre ce problème, vous pouvez passer la taille du tampon à GetWC, mais vous avez alors à peu près la même interface que mbstowcs elle-même. Vous pouvez également allouer un nouveau tampon à l'intérieur de GetWC et y renvoyer un pointeur, en laissant à l'appelant le soin de libérer le tampon.

2
Greg Hewgill

Votre problème n’a rien à voir avec les encodages, c’est une simple question de compréhension du C++ de base. Vous retournez un pointeur sur une variable locale de votre fonction, qui sera hors de portée lorsque tout le monde pourra l'utiliser, créant ainsi comportement non défini (c'est-à-dire une erreur de programmation).

Suivez cette règle d'or: "Si vous utilisez des pointeurs de caractères nus, vous vous trompez. (Sauf dans les cas où vous ne l'êtes pas.)"

J'ai déjà posté du code pour faire la conversion et communiquer les entrées et les sorties en C++ std::string et std::wstring objets.

1
Kerrek SB

J'ai fait quelque chose comme ça. Les 2 premiers zéros sont parce que je ne sais pas quel type de type de caractères ascii cette commande veut de moi. Le sentiment général que j'avais était de créer un tableau de caractères temporaire. passer dans le tableau de caractères larges. boom. Ça marche. Le +1 garantit que le caractère final nul est au bon endroit.

char tempFilePath[MAX_PATH] = "I want to convert this to wide chars";

int len = strlen(tempFilePath);

// Converts the path to wide characters
    int needed = MultiByteToWideChar(0, 0, tempFilePath, len + 1, strDestPath, len + 1);
1
Gandalf458