web-dev-qa-db-fra.com

C ++ Convertir une chaîne (ou un caractère *) en chaîne (ou wchar_t *)

string s = "おはよう";
wstring ws = FUNCTION(s, ws);

Comment pourrais-je attribuer le contenu de s à ws?

Recherche Google et utilisé certaines techniques, mais ils ne peuvent pas attribuer le contenu exact. Le contenu est déformé.

153
Samir

En supposant que la chaîne d'entrée dans votre exemple (は よ) soit une codée UTF-8 (ce qui ne l'est pas, à première vue, mais supposons que ce soit pour des raisons explicatives :-)) d'une chaîne Unicode de votre intérêt, alors votre problème peut être entièrement résolu avec la bibliothèque standard (C++ 11 et plus récent) seul.

La version TL; DR:

#include <locale>
#include <codecvt>
#include <string>

std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string narrow = converter.to_bytes(wide_utf16_source_string);
std::wstring wide = converter.from_bytes(narrow_utf8_source_string);

Exemple plus long compilable et exécutable en ligne:

(Ils montrent tous le même exemple. Il y en a beaucoup pour la redondance ...)

Note (ancien) :

Comme indiqué dans les commentaires et expliqué dans le https://stackoverflow.com/a/17106065/6345 , l'utilisation de la bibliothèque standard pour convertir les fichiers UTF-8 en UTF-16 peut donner des résultats inattendus. différences dans les résultats sur différentes plateformes. Pour une meilleure conversion, considérez std::codecvt_utf8 comme décrit sur http://en.cppreference.com/w/cpp/locale/codecvt_utf8

Note (nouveau) :

Étant donné que l'en-tête codecvt est obsolète en C++ 17, certaines inquiétudes concernant la solution présentée dans cette réponse ont été soulevées. Cependant, le comité des normes C++ a ajouté une déclaration importante dans http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html en disant

cette composante de bibliothèque doit être retirée de l’Annexe D, avec elle, jusqu’à ce qu’un produit de remplacement approprié soit normalisé.

Ainsi, dans un avenir prévisible, la solution codecvt de cette réponse est sûre et portable.

212
Johann Gerell
int StringToWString(std::wstring &ws, const std::string &s)
{
    std::wstring wsTmp(s.begin(), s.end());

    ws = wsTmp;

    return 0;
}
48
Pietro M

Votre question est sous-spécifiée. Strictement, cet exemple est une erreur de syntaxe. Cependant, std::mbstowcs est probablement ce que vous recherchez.

C'est une fonction de la bibliothèque C qui opère sur les tampons, mais voici un idiome facile à utiliser, gracieuseté de TBohne (anciennement Mooing Duck):

_std::wstring ws(s.size(), L' '); // Overestimate number of code points.
ws.resize(std::mbstowcs(&ws[0], s.c_str(), s.size())); // Shrink to fit.
_
28
Potatoswatter

API Windows uniquement, avant la mise en œuvre C++ 11, au cas où quelqu'un en aurait besoin:

#include <stdexcept>
#include <vector>
#include <windows.h>

using std::runtime_error;
using std::string;
using std::vector;
using std::wstring;

wstring utf8toUtf16(const string & str)
{
   if (str.empty())
      return wstring();

   size_t charsNeeded = ::MultiByteToWideChar(CP_UTF8, 0, 
      str.data(), (int)str.size(), NULL, 0);
   if (charsNeeded == 0)
      throw runtime_error("Failed converting UTF-8 string to UTF-16");

   vector<wchar_t> buffer(charsNeeded);
   int charsConverted = ::MultiByteToWideChar(CP_UTF8, 0, 
      str.data(), (int)str.size(), &buffer[0], buffer.size());
   if (charsConverted == 0)
      throw runtime_error("Failed converting UTF-8 string to UTF-16");

   return wstring(&buffer[0], charsConverted);
}
17
Alex Che

Si vous utilisez Windows/Visual Studio et avez besoin de convertir une chaîne en wstring, vous pouvez utiliser:

#include <AtlBase.h>
#include <atlconv.h>
...
string s = "some string";
CA2W ca2w(s.c_str());
wstring w = ca2w;
printf("%s = %ls", s.c_str(), w.c_str());

Même procédure pour convertir une chaîne de caractères en chaîne (vous devrez parfois spécifier une page de code):

#include <AtlBase.h>
#include <atlconv.h>
...
wstring w = L"some wstring";
CW2A cw2a(w.c_str());
string s = cw2a;
printf("%s = %ls", s.c_str(), w.c_str());

Vous pouvez spécifier codepage et même UTF8 (c'est plutôt agréable de travailler avec JNI/Java).

CA2W ca2w(str, CP_UTF8);

Si vous voulez en savoir plus sur codepages, il existe un article intéressant sur Joel on Software: Le minimum absolu que chaque développeur de logiciel a absolument, doit savoir de manière positive sur Unicode et les jeux de caractères .

Ces macros CA2W (Convertir Ansi en Wide = unicode) font partie de Macros de conversion de chaînes ATL et MFC , exemples inclus.

Parfois, vous devrez désactiver l'avertissement de sécurité n ° 4995 '. Je ne connais pas d'autre solution (pour moi, cela se produit lorsque j'ai compilé pour Windows XP dans VS2012).

#pragma warning(Push)
#pragma warning(disable: 4995)
#include <AtlBase.h>
#include <atlconv.h>
#pragma warning(pop)

Edit: Eh bien, selon cet article l'article de Joel semble être: "tout en divertissant, il est assez léger sur détails techniques réels ". Article: Ce que chaque programmeur a absolument besoin de savoir sur le codage et les jeux de caractères pour travailler avec du texte .

12
lmiguelmh

De char* à wstring:

char* str = "hello worlddd";
wstring wstr (str, str+strlen(str));

De string à wstring:

string str = "hello worlddd";
wstring wstr (str.begin(), str.end());

Notez que cela ne fonctionne bien que si la chaîne en cours de conversion ne contient que des caractères ASCII.

10
Ghominejad

Voici un moyen de combiner string, wstring et des constantes de chaîne mélangée à 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();
10
Mark Lakata

en utilisant Boost.Locale:

ws = boost::locale::conv::utf_to_utf<wchar_t>(s);
6
vladon

Cette variante est ma préférée dans la vie réelle. Il convertit l'entrée, si elle est valide UTF-8, en wstring respective. Si l'entrée est corrompue, la wstring est construite à partir des octets simples. Ceci est extrêmement utile si vous n’êtes pas vraiment sûr de la qualité de vos données d’entrée.

std::wstring convert(const std::string& input)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
        return converter.from_bytes(input);
    }
    catch(std::range_error& e)
    {
        size_t length = input.length();
        std::wstring result;
        result.reserve(length);
        for(size_t i = 0; i < length; i++)
        {
            result.Push_back(input[i] & 0xFF);
        }
        return result;
    }
}
5
Matthias Ronge

la méthode s2ws fonctionne bien. L'espoir aide.

std::wstring s2ws(const std::string& s) {
    std::string curLocale = setlocale(LC_ALL, ""); 
    const char* _Source = s.c_str();
    size_t _Dsize = mbstowcs(NULL, _Source, 0) + 1;
    wchar_t *_Dest = new wchar_t[_Dsize];
    wmemset(_Dest, 0, _Dsize);
    mbstowcs(_Dest,_Source,_Dsize);
    std::wstring result = _Dest;
    delete []_Dest;
    setlocale(LC_ALL, curLocale.c_str());
    return result;
}
1
hahakubile

Basé sur mes propres tests (sous Windows 8, vs2010), mbstowcs peut réellement endommager la chaîne d'origine, il ne fonctionne qu'avec la page de code ANSI. Si MultiByteToWideChar/WideCharToMultiByte peut également causer une corruption de chaîne - mais ils ont tendance à remplacer les caractères qu'ils ne connaissent pas avec "?". points d’interrogation, mais mbstowcs a tendance à s’arrêter quand il rencontre un caractère inconnu et coupe la chaîne à cet endroit précis. (J'ai testé des caractères vietnamiens sur des fenêtres finlandaises).

Préférez donc la fonction api Multi * à Windows par rapport aux fonctions C analogi.

De plus, ce que j’ai remarqué comme moyen le plus rapide de coder une chaîne de pages de code est de ne pas utiliser les appels de fonction api MultiByteToWideChar/WideCharToMultiByte mais leurs macros analogiques ATL: W2A/A2W.

Ainsi, la fonction analogique mentionnée ci-dessus ressemblerait à ceci:

wstring utf8toUtf16(const string & str)
{
   USES_CONVERSION;
   _acp = CP_UTF8;
   return A2W( str.c_str() );
}

_acp est déclaré dans la macro USES_CONVERSION.

Ou encore des fonctions qui me manquent souvent lors de la conversion de données anciennes en nouvelles:

string ansi2utf8( const string& s )
{
   USES_CONVERSION;
   _acp = CP_ACP;
   wchar_t* pw = A2W( s.c_str() );

   _acp = CP_UTF8;
   return W2A( pw );
}

Mais notez que ces macros utilisent beaucoup la pile (n'utilisez pas de boucles for boucle ou récursives pour la même fonction) - après avoir utilisé la macro W2A ou A2W - il est préférable de renvoyer ASAP afin que la pile soit libérée de la conversion temporaire.

1
TarmoPikaro

Chaîne à wstring

std::wstring Str2Wstr(const std::string& str)
{
    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;
}

wstring to String

std::string Wstr2Str(const std::wstring& wstr)
{
    typedef std::codecvt_utf8<wchar_t> convert_typeX;
    std::wstring_convert<convert_typeX, wchar_t> converterX;
    return converterX.to_bytes(wstr);
}
1
Isma Rekathakusuma

Si vous avez QT et si vous êtes paresseux pour implémenter une fonction et des choses que vous pouvez utiliser

std :: string str; QString (str) .toStdWString ()

0