Comment convertir wstring en chaîne?

204

La question est de savoir comment convertir wstring en chaîne?

J'ai l'exemple suivant:

#include <string>
#include <iostream>

int main()
{
    std::wstring ws = L"Hello";
    std::string s( ws.begin(), ws.end() );

  //std::cout <<"std::string =     "<<s<<std::endl;
    std::wcout<<"std::wstring =    "<<ws<<std::endl;
    std::cout <<"std::string =     "<<s<<std::endl;
}

la sortie avec la ligne commentée est:

std::string =     Hello
std::wstring =    Hello
std::string =     Hello

mais sans c'est seulement:

std::wstring =    Hello

Quelque chose ne va pas dans l'exemple? Puis-je faire la conversion comme ci-dessus?

ÉDITER

Un nouvel exemple (en tenant compte de certaines réponses) est

#include <string>
#include <iostream>
#include <sstream>
#include <locale>

int main()
{
    setlocale(LC_CTYPE, "");

    const std::wstring ws = L"Hello";
    const std::string s( ws.begin(), ws.end() );

    std::cout<<"std::string =     "<<s<<std::endl;
    std::wcout<<"std::wstring =    "<<ws<<std::endl;

    std::stringstream ss;
    ss << ws.c_str();
    std::cout<<"std::stringstream =     "<<ss.str()<<std::endl;
}

La sortie est:

std::string =     Hello
std::wstring =    Hello
std::stringstream =     0x860283c

par conséquent, le flux de chaînes ne peut pas être utilisé pour convertir wstring en chaîne.

BЈовић
la source
4
Comment pouvez-vous poser cette question sans spécifier également les encodages?
David Heffernan
5
@tenfour: Pourquoi utiliser std::wstringdu tout? stackoverflow.com/questions/1049947/…
dalle
11
@dalle Si vous avez des données déjà encodées en UTF-16, le fait que l'UTF-16 soit ou non considéré comme nuisible est quelque peu discutable. Et pour ce que ça vaut, je ne pense pas qu'une forme de transformation soit nuisible; ce qui est nocif, c'est que les gens pensent comprendre l'Unicode alors qu'en fait ils ne le font pas.
David Heffernan,
2
Doit-il s'agir d'une solution multiplateforme?
ali_bahoo
2
@dalle c ++ standard ne mentionne en aucun cas utf (utf-8 ou utf-16). Vous avez un lien où il est dit pourquoi utf-16 ne peut pas être encodé avec wstring?
BЈовић

Réponses:

31

Voici une solution élaborée basée sur les autres suggestions:

#include <string>
#include <iostream>
#include <clocale>
#include <locale>
#include <vector>

int main() {
  std::setlocale(LC_ALL, "");
  const std::wstring ws = L"ħëłlö";
  const std::locale locale("");
  typedef std::codecvt<wchar_t, char, std::mbstate_t> converter_type;
  const converter_type& converter = std::use_facet<converter_type>(locale);
  std::vector<char> to(ws.length() * converter.max_length());
  std::mbstate_t state;
  const wchar_t* from_next;
  char* to_next;
  const converter_type::result result = converter.out(state, ws.data(), ws.data() + ws.length(), from_next, &to[0], &to[0] + to.size(), to_next);
  if (result == converter_type::ok or result == converter_type::noconv) {
    const std::string s(&to[0], to_next);
    std::cout <<"std::string =     "<<s<<std::endl;
  }
}

Cela fonctionnera généralement pour Linux, mais créera des problèmes sous Windows.

Philipp
la source
@Phillip: quelle partie du code dépend de la c-locale? est-ce std::setlocale(LC_ALL, "");vraiment nécessaire?
smerlin
2
l'utilisation std::wcout.imbue(locale)devrait également faire le travail, et elle a l'avantage de ne changer aucun état global.
smerlin
32
Le std::wstring_convertC ++ 11 résume une grande partie de ce bruit.
Cubbi
7
@Philipp, que voulez-vous dire par "va créer des problèmes sur Windows"? Quel genre de problemes?
Gili
1
Le code ci-dessus donne (tel que copié) me donne un *** glibc detected *** test: malloc(): smallbin double linked list corrupted: 0x000000000180ea30 ***sur Linux 64 bits (gcc 4.7.3). Quelqu'un d'autre vit ça?
hogliux
312

Comme Cubbi l'a souligné dans l'un des commentaires, std::wstring_convert(C ++ 11) fournit une solution simple et soignée (vous devez #include <locale>et <codecvt>):

std::wstring string_to_convert;

//setup converter
using convert_type = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_type, wchar_t> converter;

//use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
std::string converted_str = converter.to_bytes( string_to_convert );

J'utilisais une combinaison d' wcstombsallocation / désallocation fastidieuse de mémoire avant de tomber sur cela.

http://en.cppreference.com/w/cpp/locale/wstring_convert

mise à jour (2013.11.28)

Un liners peut être déclaré ainsi (merci Guss pour votre commentaire):

std::wstring str = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes("some string");

Les fonctions d'encapsuleur peuvent être définies comme suit: (Merci ArmanSchwarz pour votre commentaire)

std::wstring s2ws(const std::string& str)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.from_bytes(str);
}

std::string ws2s(const std::wstring& wstr)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.to_bytes(wstr);
}

Remarque: il y a une certaine controverse quant à savoir si string/ wstringdevrait être passé aux fonctions en tant que références ou en tant que littéraux (en raison de C ++ 11 et des mises à jour du compilateur). Je laisse la décision à la personne chargée de la mise en œuvre, mais cela vaut la peine de le savoir.

Remarque: J'utilise std::codecvt_utf8dans le code ci-dessus, mais si vous n'utilisez pas UTF-8, vous devrez le changer pour le codage approprié que vous utilisez:

http://en.cppreference.com/w/cpp/header/codecvt

dk123
la source
25
Veuillez +1 : il s'agit de la méthode standard C ++ officielle de conversion de chaîne. Vous pouvez également utiliser from_bytes pour convertir dans l'autre sens. Parce que personnellement j'aime les one-liners, voici ma version:std::wstring str = std::wstring_convert<std::codecvt_utf<wchar_t>>().from_bytes("some string");
Guss
7
Il semble que en.cppreference.com/w/cpp/header/codecvt ne soit pas disponible à partir de g ++ 4.8.2. Les deux méthodes s2ws et ws2s ne fonctionnent pas actuellement sous linux
Begui
5
Il semble que cela soit obsolète ( stackoverflow.com/a/42946556/211176 ). Mon compilateur génère des erreurs lorsque j'essaie d'exécuter ce code
adam_0
5
Pour tous ceux qui s'inquiètent de C ++ 17 et d'une compatibilité supplémentaire (en raison de la dépréciation), voir: stackoverflow.com/a/18597384/6205379
Timo
128

Solution de: http://forums.devshed.com/c-programming-42/wstring-to-string-444006.html

std::wstring wide( L"Wide" ); 
std::string str( wide.begin(), wide.end() );

// Will print no problemo!
std::cout << str << std::endl;

Attention , aucune conversion de jeu de caractères n'est en cours ici. Ce que cela fait est simplement d'affecter chaque itération wchar_tà une char- une conversion tronquée. Il utilise la chaîne std :: string :

template< class InputIt >
basic_string( InputIt first, InputIt last,
              const Allocator& alloc = Allocator() );

Comme indiqué dans les commentaires:

les valeurs 0-127 sont identiques dans pratiquement tous les encodages, donc la troncature de valeurs inférieures à 127 donne le même texte. Mettez un caractère chinois et vous verrez l'échec.

-

les valeurs 128-255 de la page de codes 1252 de Windows (la valeur par défaut de Windows en anglais) et les valeurs 128-255 de l'unicode sont généralement les mêmes, donc si c'est la page de codes que vous utilisez, la plupart de ces caractères doivent être tronqués aux valeurs correctes. (Je m'attendais totalement à ce que á et õ fonctionnent, je sais que notre code au travail repose sur ceci pour é, que je corrigerai bientôt)

Et notez que les points de code dans la gamme 0x80 - 0x9Fde Win1252 ne pas fonctionner. Cela comprend , œ, ž, Ÿ, ...

namar0x0309
la source
2
Bizarrement, cela fonctionne sur Visual Studio 10. Que se passe-t-il? Cela devrait provoquer une affectation tronquée de wchar_t à char pour tous les éléments de la chaîne d'origine.
Pedro Lamarão
6
... lorsqu'il s'agit de caractères non latins.
JavaRunner
8
@ PedroLamarão: les valeurs 0-127 sont identiques dans pratiquement tous les encodages, donc tronquer les valeurs qui sont toutes inférieures à 127 donne le même texte. Mettez un caractère chinois et vous verrez l'échec.
Mooing Duck
3
@ PedroLamarão: les valeurs 128-255 de la page de codes 1252 de Windows (la valeur par défaut de Windows en anglais) et les valeurs 128-255 de l'unicode sont généralement les mêmes, donc si c'est la page de codes que vous utilisez, la plupart de ces caractères doivent être tronqués à la bonne valeurs. (Je m'attendais totalement à ce que á et õ fonctionnent, je sais que notre code au travail repose sur cela pour é, que je corrigerai bientôt)
Mooing Duck
2
Cela fonctionne très bien. MSVS 2015 et MSVS 2017 et MINGW / g ++ et clang ++. Legit ++ 1.
Nikos
11

Au lieu d'inclure les paramètres régionaux et toutes ces choses fantaisistes, si vous savez pour FACT que votre chaîne est convertible, faites simplement ceci:

#include <iostream>
#include <string>

using namespace std;

int main()
{
  wstring w(L"bla");
  string result;
  for(char x : w)
    result += x;

  cout << result << '\n';
}

Exemple en direct ici

rubenvb
la source
2
+1 parce que c'est une solution simple qui fonctionne pour certains scénarios (pour une définition vague de "travaux", je pourrais ajouter).
corbeau
2
Presque la même chose que la solution de namar0x0309, qui est beaucoup plus élégante à mon humble avis. Mais c'est juste moi.
onitake
J'ai modifié votre code pour qu'il fonctionne réellement avec un minimum de modifications ;-)
rubenvb
9
-1 Si vous avez un wstring, il est probable que vous ayez affaire à des caractères multi-octets. Si vous pouviez savoir que la chaîne est trivialement convertible, vous ne manipuleriez pas un wstring en premier lieu. Plus probablement, vous avez affaire à une autre bibliothèque qui s'attend à ce que vous gériez correctement le wstring. Tronquer les wchars ne fait que mendier un bug difficile à retrouver plus tard. De plus, vous devez utiliser "string result (w.begin (), w.end ());" si vous deviez le faire, pour éviter une boucle qui pourrait déclencher de nombreuses réallocations.
Kian
7

Je crois que la manière officielle est toujours de parcourir les codecvtfacettes (vous avez besoin d'une traduction adaptée aux paramètres régionaux), comme dans

resultCode = use_facet<codecvt<char, wchar_t, ConversionState> >(locale).
  in(stateVar, scratchbuffer, scratchbufferEnd, from, to, toLimit, curPtr);

ou quelque chose comme ça, je n'ai pas de code de travail qui traîne. Mais je ne sais pas combien de personnes utilisent ces machines de nos jours et combien demandent simplement des pointeurs à la mémoire et laissent ICU ou une autre bibliothèque gérer les détails sanglants.

Christopher Creutzig
la source
7

Il y a deux problèmes avec le code:

  1. La conversion en const std::string s( ws.begin(), ws.end() );n'est pas requise pour mapper correctement les caractères larges à leur homologue étroit. Très probablement, chaque caractère large sera simplement transtypé en char.
    La résolution de ce problème est déjà donnée dans la réponse de kem et implique la narrowfonction de la ctypefacette des paramètres régionaux .

  2. Vous écrivez la sortie à la fois std::coutet std::wcoutdans le même programme. Les deux coutet wcoutsont associés au même flux ( stdout) et les résultats de l'utilisation du même flux à la fois comme flux orienté octet (comme le coutfait) et comme flux orienté large (comme le wcoutfait) ne sont pas définis.
    La meilleure option est d'éviter de mélanger une sortie étroite et large au même flux (sous-jacent). Pour stdout/ cout/ wcout, vous pouvez essayer de changer l'orientation de stdoutlorsque vous passez d'une sortie large à une sortie étroite (ou vice versa):

    #include <iostream>
    #include <stdio.h>
    #include <wchar.h>
    
    int main() {
        std::cout << "narrow" << std::endl;
        fwide(stdout, 1); // switch to wide
        std::wcout << L"wide" << std::endl;
        fwide(stdout, -1); // switch to narrow
        std::cout << "narrow" << std::endl;
        fwide(stdout, 1); // switch to wide
        std::wcout << L"wide" << std::endl;
    }
Bart van Ingen Schenau
la source
Oui, cela résout le problème avec l'utilisation de cout et wcout.
BЈовић
7

Encodage par défaut sur:

  • Windows UTF-16.
  • Linux UTF-8.
  • MacOS UTF-8.

Ce code a deux formes pour convertir std :: string en std :: wstring et std :: wstring en std :: string. Si vous annulez # si WIN32 défini, vous obtenez le même résultat.

1. std :: string à std :: wstring

MultiByteToWideChar WinAPI

_mbstowcs_s_l

#if defined WIN32
#include <windows.h>
#endif

std::wstring StringToWideString(std::string str)
{
    if (str.empty())
    {
        return std::wstring();
    }
    size_t len = str.length() + 1;
    std::wstring ret = std::wstring(len, 0);
#if defined WIN32
    int size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, &str[0], str.size(), &ret[0], len);
    ret.resize(size);
#else
    size_t size = 0;
    _locale_t lc = _create_locale(LC_ALL, "en_US.UTF-8");
    errno_t retval = _mbstowcs_s_l(&size, &ret[0], len, &str[0], _TRUNCATE, lc);
    _free_locale(lc);
    ret.resize(size - 1);
#endif
    return ret;
}

2. std :: wstring à std :: string

WideCharToMultiByte WinAPI

_wcstombs_s_l

std::string WidestringToString(std::wstring wstr)
{
    if (wstr.empty())
    {
        return std::string();
    }
#if defined WIN32
    int size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &wstr[0], wstr.size(), NULL, 0, NULL, NULL);
    std::string ret = std::string(size, 0);
    WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, &wstr[0], wstr.size(), &ret[0], size, NULL, NULL);
#else
    size_t size = 0;
    _locale_t lc = _create_locale(LC_ALL, "en_US.UTF-8");
    errno_t err = _wcstombs_s_l(&size, NULL, 0, &wstr[0], _TRUNCATE, lc);
    std::string ret = std::string(size, 0);
    err = _wcstombs_s_l(&size, &ret[0], size, &wstr[0], _TRUNCATE, lc);
    _free_locale(lc);
    ret.resize(size - 1);
#endif
    return ret;
}

3. Sous Windows, vous devez imprimer unicode à l'aide de WinAPI.

WriteConsole

#if defined _WIN32
    void WriteLineUnicode(std::string s)
    {
        std::wstring unicode = StringToWideString(s);
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), unicode.c_str(), unicode.length(), NULL, NULL);
        std::cout << std::endl;
    }

    void WriteUnicode(std::string s)
    {
        std::wstring unicode = StringToWideString(s);
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), unicode.c_str(), unicode.length(), NULL, NULL);
    }

    void WriteLineUnicode(std::wstring ws)
    {
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), ws.c_str(), ws.length(), NULL, NULL);
        std::cout << std::endl;
    }

    void WriteUnicode(std::wstring ws)
    {
        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), ws.c_str(), ws.length(), NULL, NULL);
    }

4. Sur le programme principal.

#if defined _WIN32
int wmain(int argc, WCHAR ** args)
#else
int main(int argc, CHAR ** args)
#endif
{
    std::string source = u8"ÜüΩωЙ你月曜日\na🐕èéøÞǽлљΣæča🐕🐕";
    std::wstring wsource = L"ÜüΩωЙ你月曜日\na🐕èéøÞǽлљΣæča🐕🐕";

    WriteLineUnicode(L"@" + StringToWideString(source) + L"@");
    WriteLineUnicode("@" + WidestringToString(wsource) + "@");
    return EXIT_SUCCESS;
}

5. Enfin, vous avez besoin d'un support puissant et complet pour les caractères unicode dans la console. Je recommande ConEmu et définit comme terminal par défaut sous Windows . Vous devez connecter Visual Studio à ConEmu. N'oubliez pas que le fichier exe de Visual Studio est devenv.exe

Testé sur Visual Studio 2017 avec VC ++; std = c ++ 17.

Résultat

Résultat1

Joma
la source
6

Vous pourriez aussi bien utiliser directement la méthode étroite de la facette ctype:

#include <clocale>
#include <locale>
#include <string>
#include <vector>

inline std :: string narrow (std :: wstring const & text)
{
    std :: locale const loc ("");
    wchar_t const * from = text.c_str ();
    std :: size_t const len ​​= text.size ();
    tampon std :: vector <char> (len + 1);
    std :: use_facet <std :: ctype <wchar_t>> (loc) .narrow (from, from + len, '_', & buffer [0]);
    return std :: string (& buffer [0], & buffer [len]);
}
légaliser
la source
6

Au moment d'écrire cette réponse, la première recherche google pour "convertir la chaîne wstring" vous atterrirait sur cette page. Ma réponse montre comment convertir une chaîne en wstring, bien que ce ne soit PAS la vraie question, et je devrais probablement supprimer cette réponse mais qui est considérée comme mauvaise. Vous voudrez peut-être passer à cette réponse StackOverflow , qui est maintenant mieux classée que cette page.


Voici un moyen de combiner des constantes chaîne, wstring et chaîne mixte à wstring. Utilisez la classe wstringstream.

#include <sstream>

std::string narrow = "narrow";
std::wstring wide = "wide";

std::wstringstream cls;
cls << " abc " << narrow.c_str() << L" def " << wide.c_str();
std::wstring total= cls.str();
Mark Lakata
la source
13
Ce n'est pas une conversion de chaîne en chaîne
poitroae
1
@Michael Pouvez-vous s'il vous plaît expliquer? Qu'en est-il incorrect? Votre commentaire n'est pas utile sans plus de détails.
Nate
1
il s'agit d'une conversion de chaîne en chaîne de caractères. c'est-à-dire l'opposé de la question.
Jeff McClintock
4

En plus de simplement convertir les types, vous devez également être conscient du format réel de la chaîne.

Lors de la compilation pour le jeu de caractères multi-octets, Visual Studio et l'API Win supposent UTF8 (en fait, l'encodage Windows qui est Windows-28591 ).
Lors de la compilation pour le jeu de caractères Unicode Visual studio et l'API Win suppose UTF16.

Ainsi, vous devez également convertir la chaîne UTF16 au format UTF8, et pas seulement la convertir en std :: string.
Cela deviendra nécessaire lorsque vous travaillez avec des formats multi-caractères comme certaines langues non latines.

L'idée est de décider que représente std::wstring toujours UTF16 .
Et représente std::string toujours UTF8 .

Ce n'est pas appliqué par le compilateur, c'est plutôt une bonne politique à avoir. Notez les préfixes de chaîne que j'utilise pour définir UTF16 ( L ) et UTF8 ( u8 ).

Pour convertir entre les 2 types, vous devez utiliser: std :: codecvt_utf8_utf16 <wchar_t>

#include <string>

#include <codecvt>

int main()
{

    std::string original8 = u8"הלו";

    std::wstring original16 = L"הלו";

    //C++11 format converter
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;

    //convert to UTF8 and std::string
    std::string utf8NativeString = convert.to_bytes(original16);

    std::wstring utf16NativeString = convert.from_bytes(original8);

    assert(utf8NativeString == original8);
    assert(utf16NativeString == original16);

    return 0;
}
Yochai Timmer
la source
3

Dans mon cas, je dois utiliser le caractère multi-octets (MBCS) et je veux utiliser std :: string et std :: wstring. Et ne peut pas utiliser c ++ 11. J'utilise donc mbstowcs et wcstombs.

Je fais la même fonction en utilisant new, delete [], mais c'est plus lent que ça.

Cela peut aider Comment: convertir entre différents types de chaînes

ÉDITER

Cependant, en cas de conversion en wstring et la chaîne source n'est pas un alphabet et une chaîne multi-octets, cela ne fonctionne pas. Je change donc wcstombs en WideCharToMultiByte.

#include <string>

std::wstring get_wstr_from_sz(const char* psz)
{
    //I think it's enough to my case
    wchar_t buf[0x400];
    wchar_t *pbuf = buf;
    size_t len = strlen(psz) + 1;

    if (len >= sizeof(buf) / sizeof(wchar_t))
    {
        pbuf = L"error";
    }
    else
    {
        size_t converted;
        mbstowcs_s(&converted, buf, psz, _TRUNCATE);
    }

    return std::wstring(pbuf);
}

std::string get_string_from_wsz(const wchar_t* pwsz)
{
    char buf[0x400];
    char *pbuf = buf;
    size_t len = wcslen(pwsz)*2 + 1;

    if (len >= sizeof(buf))
    {
        pbuf = "error";
    }
    else
    {
        size_t converted;
        wcstombs_s(&converted, buf, pwsz, _TRUNCATE);
    }

    return std::string(pbuf);
}

EDIT pour utiliser «MultiByteToWideChar» au lieu de «wcstombs»

#include <Windows.h>
#include <boost/shared_ptr.hpp>
#include "string_util.h"

std::wstring get_wstring_from_sz(const char* psz)
{
    int res;
    wchar_t buf[0x400];
    wchar_t *pbuf = buf;
    boost::shared_ptr<wchar_t[]> shared_pbuf;

    res = MultiByteToWideChar(CP_ACP, 0, psz, -1, buf, sizeof(buf)/sizeof(wchar_t));

    if (0 == res && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    {
        res = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);

        shared_pbuf = boost::shared_ptr<wchar_t[]>(new wchar_t[res]);

        pbuf = shared_pbuf.get();

        res = MultiByteToWideChar(CP_ACP, 0, psz, -1, pbuf, res);
    }
    else if (0 == res)
    {
        pbuf = L"error";
    }

    return std::wstring(pbuf);
}

std::string get_string_from_wcs(const wchar_t* pcs)
{
    int res;
    char buf[0x400];
    char* pbuf = buf;
    boost::shared_ptr<char[]> shared_pbuf;

    res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, buf, sizeof(buf), NULL, NULL);

    if (0 == res && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    {
        res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, NULL, 0, NULL, NULL);

        shared_pbuf = boost::shared_ptr<char[]>(new char[res]);

        pbuf = shared_pbuf.get();

        res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, pbuf, res, NULL, NULL);
    }
    else if (0 == res)
    {
        pbuf = "error";
    }

    return std::string(pbuf);
}
il est sur
la source
Comment puis-je utiliser "wcstombs_s" avec gcc 4.8? Parce que je vois que c'est la fonctionnalité C ++ 11.
cristian
@cristian Vous pouvez utiliser la version "non sûre" de cette fonction wcstombs().
Vizor
3

Cette solution est inspirée de la solution de dk123 , mais utilise une facette codecvt dépendante des paramètres régionaux. Le résultat est dans une chaîne codée locale au lieu de UTF-8 (si elle n'est pas définie comme locale):

std::string w2s(const std::wstring &var)
{
   static std::locale loc("");
   auto &facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
   return std::wstring_convert<std::remove_reference<decltype(facet)>::type, wchar_t>(&facet).to_bytes(var);
}

std::wstring s2w(const std::string &var)
{
   static std::locale loc("");
   auto &facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
   return std::wstring_convert<std::remove_reference<decltype(facet)>::type, wchar_t>(&facet).from_bytes(var);
}

Je le cherchais, mais je ne le trouve pas. Enfin, j'ai trouvé que je peux obtenir la bonne facette en std::localeutilisant la std::use_facet()fonction avec le bon nom de type. J'espère que cela t'aides.

Visière
la source
Vizor, quels sont les avantages (le cas échéant) de la conversion avec la facette dépendante des paramètres régionaux?
Marc.2377
Si vous travaillez avec des chaînes du système, depuis l'entrée de la console par exemple.
Vizor
1

Au cas où quelqu'un d'autre serait intéressé: j'avais besoin d'une classe qui pourrait être utilisée de manière interchangeable où que ce soit stringou wstringétait prévu. La classe suivante convertible_string, basée sur la solution de dk123 , peut être initialisé soit avec un string, char const*, wstringou wchar_t const*et peut être affecté par ou converti implicitement soit à un stringou wstring(peut donc être passé dans une des fonctions qui prennent soit).

class convertible_string
{
public:
    // default ctor
    convertible_string()
    {}

    /* conversion ctors */
    convertible_string(std::string const& value) : value_(value)
    {}
    convertible_string(char const* val_array) : value_(val_array)
    {}
    convertible_string(std::wstring const& wvalue) : value_(ws2s(wvalue))
    {}
    convertible_string(wchar_t const* wval_array) : value_(ws2s(std::wstring(wval_array)))
    {}

    /* assignment operators */
    convertible_string& operator=(std::string const& value)
    {
        value_ = value;
        return *this;
    }
    convertible_string& operator=(std::wstring const& wvalue)
    {
        value_ = ws2s(wvalue);
        return *this;
    }

    /* implicit conversion operators */
    operator std::string() const { return value_; }
    operator std::wstring() const { return s2ws(value_); }
private:
    std::string value_;
};
James Hirschorn
la source
1
Je préfère stocker un std::wstringdans la classe, plutôt que de stocker std::stringet de faire une conversion en std::wstringcas de besoin pour obtenir un std::wstring. Parce que std::wstringc'est un peu plus rapide std::stringet mieux compatible. Même il consomme plus de mémoire que std::string.
0xAA55
0
#include <boost/locale.hpp>
namespace lcv = boost::locale::conv;

inline std::wstring fromUTF8(const std::string& s)
{ return lcv::utf_to_utf<wchar_t>(s); }

inline std::string toUTF8(const std::wstring& ws)
{ return lcv::utf_to_utf<char>(ws); }
deep125
la source
-1

J'utilise ci-dessous pour convertir wstring en chaîne.

std::string strTo;
char *szTo = new char[someParam.length() + 1];
szTo[someParam.size()] = '\0';
WideCharToMultiByte(CP_ACP, 0, someParam.c_str(), -1, szTo, (int)someParam.length(), NULL, NULL);
strTo = szTo;
delete szTo;
Arun
la source
Vous semblez manquer un en-tête standard ( <string>) et une définition pour WideCharToMultiByte()- est-ce un wrapper autour std::wctomb()?
Toby Speight
-3
// Embarcadero C++ Builder 

// convertion string to wstring
string str1 = "hello";
String str2 = str1;         // typedef UnicodeString String;   -> str2 contains now u"hello";

// convertion wstring to string
String str2 = u"hello";
string str1 = UTF8string(str2).c_str();   // -> str1 contains now "hello"
necips
la source
3
veuillez expliquer ce que vous faites là dans votre réponse, sinon cela pourrait être
supprimé
1
D'où vient la fonction UTF8string?
Jean-Christophe Blanchard