Je ne pense pas qu'il stringsaccepte les caractères> 8 bits. Est-il déjà encodé en UTF-8?
kennytm
3
Quel est le codage de votre système pour créer "おはよう"une chaîne codée par le système?
sbi
Je crois que MSVC acceptera cela et en fera un encodage multi-octets, peut-être UTF-8.
Potatoswatter le
1
@Potatoswatter: MSVC n'utilise pas UTF-8 par défaut pour TOUT. Si vous entrez ces caractères, il vous demande dans quel encodage convertir le fichier et la page de code par défaut est 1252.
Mooing Duck
2
@Samir: le plus important est quel est l'encodage du fichier ? Pouvez-vous déplacer cette chaîne au début du fichier et afficher un hexdump de cette partie? Nous pouvons probablement l'identifier à partir de là.
Mooing Duck
Réponses:
239
En supposant que la chaîne d'entrée dans votre exemple (お は よ う) est une représentation encodée en UTF-8 (ce qui n'est pas le cas, à première vue, mais supposons que ce soit pour cette explication :-)) représentation 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) seule.
Comme indiqué dans les commentaires et expliqué dans https://stackoverflow.com/a/17106065/6345, il existe des cas où l'utilisation de la bibliothèque standard pour convertir entre UTF-8 et UTF-16 peut donner des différences inattendues dans les résultats sur différentes plates-formes . Pour une meilleure conversion, considérez std::codecvt_utf8comme décrit sur http://en.cppreference.com/w/cpp/locale/codecvt_utf8
Remarque (nouveau) :
Étant donné que l'en- codecvttête 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 disant
ce composant de bibliothèque devrait être retiré à l'annexe D, parallèlement, jusqu'à ce qu'un remplacement approprié soit normalisé.
Donc, dans un avenir prévisible, la codecvtsolution de cette réponse est sûre et portable.
Cela ne fonctionne que si tous les caractères sont à un octet, c'est-à-dire ASCII ou ISO-8859-1 . Tout ce qui est multi-octet échouera misérablement, y compris UTF-8. La question contient clairement des caractères multi-octets.
Mark Ransom
28
Cette réponse est clairement insuffisante et ne fait que copier les caractères étroits tels quels en caractères larges. Voir les autres réponses, en particulier celle de Johann Gerell, pour savoir comment passer correctement d'une chaîne codée multi-octets ou utf8 à une chaîne wstring utf16.
DLRdave
10
cette réponse est dangereuse et cassera probablement sur un système non-ascii. c'est-à-dire qu'un nom de fichier arabe sera mutilé par ce hack.
Stephen
9
Cette réponse est utile si vous ignorez la nuance du corps de la question et que vous vous concentrez sur le titre de la question, ce qui m'a amené ici de Google. Tel quel, le titre de la question est extrêmement trompeur et devrait être modifié pour refléter la vraie question posée
Anne Quinn
3
Cela ne fonctionne que pour les caractères ASCII 7 bits. Pour latin1, cela ne fonctionne que si char est configuré comme non signé. Si le type char est signé (ce qui est la plupart du temps le cas), les caractères> 127 donneront des résultats erronés.
huyc
32
Votre question est sous-spécifiée. Strictement, cet exemple est une erreur de syntaxe. Cependant, std::mbstowcsc'est probablement ce que vous recherchez.
C'est une fonction de bibliothèque C et fonctionne sur des 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.
@Samir: Vous devez vous assurer que l'encodage d'exécution est le même que l'encodage à la compilation. Vous devrez peut-être setlocaleou ajuster les indicateurs du compilateur. Je ne sais pas parce que je n'utilise pas Windows, mais c'est pourquoi ce n'est pas une fonctionnalité courante. Considérez l'autre réponse si possible.
@WaffleSouffle C'est dépassé. Des implémentations contiguës sont nécessaires depuis 2011 et les implémentations abandonnent ces astuces bien avant cela.
Potatoswatter
1
et certains environnements comme mingw n'ont toujours pas l'en-tête codecvt, donc certaines des `` meilleures '' solutions plus tôt ne fonctionnent pas, ce qui signifie que ce problème n'a toujours pas de bonnes solutions dans mingw même en décembre 2014
Brian Jack
18
API Windows uniquement, implémentation antérieure à C ++ 11, au cas où quelqu'un en aurait besoin:
Vous pouvez l'optimiser. Il n'est pas nécessaire de faire une double copie de la chaîne en utilisant un vector. Réserver simplement les caractères de la chaîne en faisant wstring strW(charsNeeded + 1);puis l' utiliser comme tampon pour la conversion: &strW[0]. Enfin, assurez-vous que le dernier null est présent après la conversion en faisantstrW[charsNeeded] = 0;
c00000fd
1
@ c00000fd, pour autant que je sache, le tampon interne std :: basic_string doit être continu uniquement depuis la norme C ++ 11. Mon code est pré C ++ 11, comme indiqué en haut de l'article. Par conséquent, le code & strW [0] ne serait pas conforme au standard et pourrait légitimement planter au moment de l'exécution.
Alex Che
13
Si vous utilisez Windows / Visual Studio et devez 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 wstring en chaîne (parfois vous devrez 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());
// // using ATL
CA2W ca2w(str, CP_UTF8);// // or the standard way taken from the answer above#include<codecvt>#include<string>// convert UTF-8 string to wstring
std::wstring utf8_to_wstring (const std::string& str){
std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;return myconv.from_bytes(str);}// convert wstring to UTF-8 string
std::string wstring_to_utf8 (const std::wstring& str){
std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;return myconv.to_bytes(str);}
Parfois, vous devrez désactiver l'avertissement de sécurité # 4995 ', je ne connais pas d'autre solution de contournement (pour moi, cela se produit lorsque j'ai compilé pour WindowsXp dans VS2012).
Désolé, je ne suis pas anglophone. Veuillez modifier comme bon vous semble.
lmiguelmh
Que se passe-t-il avec le downvoter? Quel est le problème avec la réponse?
lmiguelmh
Probablement le fait qu'il favorise le code non portable.
Pavel Minaev
Oui, c'est pourquoi j'ai déclaré que cela ne fonctionne que dans Windows / Visual Studio. Mais au moins cette solution est correcte, et pas celle-ci:char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
lmiguelmh
Remarque supplémentaire: CA2W est sous l'espace de noms d'ATL. (ATL :: CA2W)
Val
12
Voici un moyen de combiner string, wstringet les constantes de chaîne mixtes à wstring. Utilisez la wstringstreamclasse.
Cela ne fonctionne PAS pour les encodages de caractères multi-octets. C'est juste une manière stupide de jeter la sécurité de type et d'étendre les caractères 7 bits de std :: string dans les 7 bits inférieurs de chaque caractère de std: wstring. Cela n'est utile que si vous avez des chaînes ASCII 7 bits et que vous devez appeler une API qui nécessite des chaînes larges.
La réponse semble intéressante. Pourriez-vous expliquer un peu: cela fonctionnera-t-il pour les encodages multi-octets, et pourquoi / comment?
wh1t3cat1k
les schémas de codage sont orthogonaux à la classe de stockage. stringstocke les caractères de 1 octet et les caractères de wstring2 octets. quelque chose comme utf8 stocke des caractères multi-octets sous la forme d'une série de valeurs de 1 octet, c'est-à-dire dans un fichier string. les classes de chaînes n'aident pas avec l'encodage. Je ne suis pas un expert de l'encodage des classes en C ++.
Mark Lakata
2
Une raison pour laquelle celle-ci n'est pas la meilleure réponse, étant donné sa simplicité et sa simplicité? Y a-t-il des cas qu'il ne couvre pas?
Ryuu
@MarkLakata, j'ai lu votre réponse au premier commentaire mais je ne suis toujours pas sûr. Cela fonctionnera-t-il pour les caractères multi-octets? En d'autres termes, n'est-elle pas sujette au même écueil que cette réponse ?
Marc 2377
@ Marc.2377 Cela ne fonctionne PAS pour les encodages de caractères multi-octets. C'est juste une façon stupide de jeter la sécurité de type et d'étendre les caractères std::string7 bits des 7 bits inférieurs de chaque caractère de std:wstring. Cela n'est utile que si vous avez des chaînes ASCII 7 bits et que vous devez appeler une API qui nécessite des chaînes larges. Regardez stackoverflow.com/a/8969776/3258851 si vous avez besoin de quelque chose de plus sophistiqué.
Parce que cela ne fonctionne que si l'encodage est Windows-1252, qui ne peut même pas contenir les lettres de la question.
Mooing Duck le
3
c'est la manière la moins sujette aux erreurs de le faire, quand vous savez que vous traitez avec ASCII. Ce qui est un cas d'utilisation important lors du portage d'applications vers des API plus récentes.
Sid Sarasvati
Ce n’est pas ainsi. Si vous utilisez Visual Studio, vous devez utiliser atlconv.h. Vérifiez les autres réponses.
Cette variante est ma préférée dans la vraie vie. Il convertit l'entrée, si elle est valide UTF-8, en la valeur respective wstring. Si l'entrée est corrompue, le wstringest construit à partir des octets uniques. Ceci est extrêmement utile si vous ne pouvez pas vraiment être sûr de la qualité de vos données d'entrée.
Qu'est-ce que toutes ces réponses allouent de la mémoire dynamique de manière non sécurisée, puis copient les données du tampon vers la chaîne? Pourquoi personne ne se débarrasse de l’intermédiaire dangereux?
Mooing Duck le
hahakubile, pouvez-vous nous aider avec quelque chose de similaire pour ws2s?
cristian le
1
Sur la base de mes propres tests (sur Windows 8, vs2010), les mbstowcs peuvent en fait endommager la chaîne d'origine, cela ne fonctionne qu'avec la page de codes ANSI. Si MultiByteToWideChar / WideCharToMultiByte peut également provoquer une corruption de chaîne - mais ils ont tendance à remplacer les caractères qu'ils ne connaissent pas par '?' points d'interrogation, mais mbstowcs a tendance à s'arrêter lorsqu'il rencontre un caractère inconnu et coupe une chaîne à ce point précis. (J'ai testé des caractères vietnamiens sur des fenêtres finlandaises).
Préférez donc la fonction API Multi * -windows aux fonctions analogiques ansi C.
De plus, ce que j'ai remarqué, le moyen le plus court d'encoder une chaîne d'une page de code à une autre n'est pas d'utiliser les appels de fonction api MultiByteToWideChar / WideCharToMultiByte, mais leurs macros ATL analogiques: W2A / A2W.
Donc, la fonction analogique mentionnée ci-dessus ressemblerait à:
Mais veuillez noter que ces macros utilisent fortement la pile - ne pas utiliser pour les boucles ou les boucles récursives pour la même fonction - après avoir utilisé la macro W2A ou A2W - mieux vaut retourner ASAP, donc la pile sera libérée de la conversion temporaire.
Ce Str2Wstr a un problème avec la terminaison 0. Il n'est plus possible de concaténer les wstrings générés via "+" (comme dans wstring s3 = s1 + s2). Je publierai bientôt une réponse résolvant ce problème. Vous devez d'abord tester les fuites de mémoire.
Cela ne fonctionnera pas non plus. Vous devrez convertir ces caractères non BMP en séquences d'échappement C.
Dave Van den Eynde
3
@Dave: cela fonctionne si votre compilateur prend en charge l'unicode dans les fichiers source, et tous ceux de la dernière décennie le font (visual studio, gcc, ...)
Thomas Bonini
Salut, quel que soit le codage système par défaut (je peux avoir l'arabe comme codage système par défaut par exemple), quel devrait être le codage du fichier de code source pour que L "お は よ う" fonctionne? devrait-il être en UTF-16, ou puis-je avoir UTF-8 sans BOM pour le codage de fichier .cpp?
Afriza N.Arief
2
@afriza: cela n'a pas vraiment d'importance tant que votre compilation le supporte
Thomas Bonini
2
Ce n'est pas une erreur; les caractères étendus dans une chaîne "étroite" sont définis pour être mappés à des séquences multi-octets. Le compilateur devrait le supporter aussi longtemps que le système d'exploitation le fait, ce qui est le moins que vous puissiez demander.
Potatoswatter
-2
utilisez ce code pour convertir votre chaîne en wstring
Notez que la question ne mentionne pas Windows et que cette réponse est uniquement Windows.
Johann Gerell
CP_ACPest certainement le mauvais argument. Tout à coup, l'état de l'environnement du thread en cours d'exécution a un effet sur le comportement du code. Pas conseillé. Spécifiez un codage de caractères fixe dans votre conversion. (Et pensez à gérer les erreurs.)
strings
accepte les caractères> 8 bits. Est-il déjà encodé en UTF-8?"おはよう"
une chaîne codée par le système?Réponses:
En supposant que la chaîne d'entrée dans votre exemple (お は よ う) est une représentation encodée en UTF-8 (ce qui n'est pas le cas, à première vue, mais supposons que ce soit pour cette explication :-)) représentation 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) seule.
La version TL; DR:
Exemple plus long compilable et exécutable en ligne:
(Ils montrent tous le même exemple. Il y en a juste beaucoup pour la redondance ...)
Remarque (ancienne) :
Comme indiqué dans les commentaires et expliqué dans https://stackoverflow.com/a/17106065/6345, il existe des cas où l'utilisation de la bibliothèque standard pour convertir entre UTF-8 et UTF-16 peut donner des différences inattendues dans les résultats sur différentes plates-formes . Pour une meilleure conversion, considérez
std::codecvt_utf8
comme décrit sur http://en.cppreference.com/w/cpp/locale/codecvt_utf8Remarque (nouveau) :
Étant donné que l'en-
codecvt
tête 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 disantDonc, dans un avenir prévisible, la
codecvt
solution de cette réponse est sûre et portable.la source
std::codecvt_utf8
pour les débutants<codecvt>
c'est obsolète depuis C ++ 17.la source
Votre question est sous-spécifiée. Strictement, cet exemple est une erreur de syntaxe. Cependant,
std::mbstowcs
c'est probablement ce que vous recherchez.C'est une fonction de bibliothèque C et fonctionne sur des tampons, mais voici un idiome facile à utiliser, gracieuseté de TBohne (anciennement Mooing Duck):
la source
setlocale
ou ajuster les indicateurs du compilateur. Je ne sais pas parce que je n'utilise pas Windows, mais c'est pourquoi ce n'est pas une fonctionnalité courante. Considérez l'autre réponse si possible.std::string ws(s.size()); ws.resize(mbstowcs(&ws[0], s.c_str(), s.size());
RAII FTWAPI Windows uniquement, implémentation antérieure à C ++ 11, au cas où quelqu'un en aurait besoin:
la source
vector
. Réserver simplement les caractères de la chaîne en faisantwstring strW(charsNeeded + 1);
puis l' utiliser comme tampon pour la conversion:&strW[0]
. Enfin, assurez-vous que le dernier null est présent après la conversion en faisantstrW[charsNeeded] = 0;
Si vous utilisez Windows / Visual Studio et devez convertir une chaîne en wstring, vous pouvez utiliser:
Même procédure pour convertir une chaîne wstring en chaîne (parfois vous devrez spécifier une page de code ):
Vous pouvez spécifier une page de code et même UTF8 (c'est assez agréable lorsque vous travaillez avec JNI / Java ). Un moyen standard de convertir un std :: wstring en utf8 std :: string est montré dans cette réponse .
Si vous voulez en savoir plus sur les pages de codes, il y a un article intéressant sur Joel sur le logiciel: le minimum absolu que chaque développeur de logiciel doit absolument, positivement savoir sur Unicode et les jeux de caractères .
Ces macros CA2W (Convert Ansi to Wide = unicode) font partie des macros de conversion de chaîne ATL et MFC , exemples inclus.
Parfois, vous devrez désactiver l'avertissement de sécurité # 4995 ', je ne connais pas d'autre solution de contournement (pour moi, cela se produit lorsque j'ai compilé pour WindowsXp dans VS2012).
Edit: Eh bien, selon cet article, l'article de Joel semble être: "tout en étant divertissant, il est assez léger sur les détails techniques réels". Article: Ce que tout programmeur doit absolument savoir sur le codage et les jeux de caractères pour travailler avec du texte .
la source
char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
Voici un moyen de combiner
string
,wstring
et les constantes de chaîne mixtes àwstring
. Utilisez lawstringstream
classe.Cela ne fonctionne PAS pour les encodages de caractères multi-octets. C'est juste une manière stupide de jeter la sécurité de type et d'étendre les caractères 7 bits de std :: string dans les 7 bits inférieurs de chaque caractère de std: wstring. Cela n'est utile que si vous avez des chaînes ASCII 7 bits et que vous devez appeler une API qui nécessite des chaînes larges.
la source
string
stocke les caractères de 1 octet et les caractères dewstring
2 octets. quelque chose comme utf8 stocke des caractères multi-octets sous la forme d'une série de valeurs de 1 octet, c'est-à-dire dans un fichierstring
. les classes de chaînes n'aident pas avec l'encodage. Je ne suis pas un expert de l'encodage des classes en C ++.std::string
7 bits des 7 bits inférieurs de chaque caractère destd:wstring
. Cela n'est utile que si vous avez des chaînes ASCII 7 bits et que vous devez appeler une API qui nécessite des chaînes larges. Regardez stackoverflow.com/a/8969776/3258851 si vous avez besoin de quelque chose de plus sophistiqué.Du
char*
auwstring
:Du
string
auwstring
:Notez que cela ne fonctionne bien que si la chaîne en cours de conversion ne contient que des caractères ASCII.
la source
atlconv.h
. Vérifiez les autres réponses.en utilisant Boost.Locale:
la source
Cette variante est ma préférée dans la vraie vie. Il convertit l'entrée, si elle est valide UTF-8, en la valeur respective
wstring
. Si l'entrée est corrompue, lewstring
est construit à partir des octets uniques. Ceci est extrêmement utile si vous ne pouvez pas vraiment être sûr de la qualité de vos données d'entrée.la source
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 (chaîne) .toStdWString ()
la source
QString
, car leQString
constructeur ne peut pas accepter une chaîne pour une raison quelconque.La méthode s2ws fonctionne bien. L'espoir aide.
la source
Sur la base de mes propres tests (sur Windows 8, vs2010), les mbstowcs peuvent en fait endommager la chaîne d'origine, cela ne fonctionne qu'avec la page de codes ANSI. Si MultiByteToWideChar / WideCharToMultiByte peut également provoquer une corruption de chaîne - mais ils ont tendance à remplacer les caractères qu'ils ne connaissent pas par '?' points d'interrogation, mais mbstowcs a tendance à s'arrêter lorsqu'il rencontre un caractère inconnu et coupe une chaîne à ce point précis. (J'ai testé des caractères vietnamiens sur des fenêtres finlandaises).
Préférez donc la fonction API Multi * -windows aux fonctions analogiques ansi C.
De plus, ce que j'ai remarqué, le moyen le plus court d'encoder une chaîne d'une page de code à une autre n'est pas d'utiliser les appels de fonction api MultiByteToWideChar / WideCharToMultiByte, mais leurs macros ATL analogiques: W2A / A2W.
Donc, la fonction analogique mentionnée ci-dessus ressemblerait à:
_acp est déclaré dans la macro USES_CONVERSION.
Ou aussi fonction qui me manque souvent lors de la conversion d'anciennes données en nouvelles:
Mais veuillez noter que ces macros utilisent fortement la pile - ne pas utiliser pour les boucles ou les boucles récursives pour la même fonction - après avoir utilisé la macro W2A ou A2W - mieux vaut retourner ASAP, donc la pile sera libérée de la conversion temporaire.
la source
Chaîne en wstring
wstring en chaîne
la source
string s = "おはよう";
est une erreur.Vous devez utiliser wstring directement:
la source
utilisez ce code pour convertir votre chaîne en wstring
la source
CP_ACP
est certainement le mauvais argument. Tout à coup, l'état de l'environnement du thread en cours d'exécution a un effet sur le comportement du code. Pas conseillé. Spécifiez un codage de caractères fixe dans votre conversion. (Et pensez à gérer les erreurs.)