No creo que stringsacepte caracteres de> 8 bits. ¿Ya está codificado en UTF-8?
kennytm
3
¿Cuál es la codificación de su sistema que haría "おはよう"una cadena codificada por el sistema?
sbi
Creo que MSVC aceptará eso y lo convertirá en una codificación multibyte, tal vez UTF-8.
Potatoswatter
1
@Potatoswatter: MSVC no usa UTF-8 por defecto para NADA. Si ingresa esos caracteres, le pregunta a qué codificación convertir el archivo y por defecto a la página de códigos 1252.
Mooing Duck
2
@Samir: lo más importante es ¿cuál es la codificación del archivo ? ¿Puedes mover esa cadena al comienzo del archivo y mostrar un hexdump de esa parte? Probablemente podamos identificarlo a partir de eso.
Mooing Duck
Respuestas:
239
Suponiendo que la cadena de entrada en su ejemplo (お は よ う) es una codificación UTF-8 (que no lo es, por lo que parece, pero supongamos que es por el bien de esta explicación :-)) representación de una cadena Unicode de su interés, entonces su problema puede resolverse completamente con la biblioteca estándar (C ++ 11 y más reciente) solo.
Como se señaló en los comentarios y se explicó en https://stackoverflow.com/a/17106065/6345, hay casos en que el uso de la biblioteca estándar para convertir entre UTF-8 y UTF-16 podría dar diferencias inesperadas en los resultados en diferentes plataformas . Para una mejor conversión, considere std::codecvt_utf8como se describe en http://en.cppreference.com/w/cpp/locale/codecvt_utf8
Nota (nueva) :
Dado que el codecvtencabezado está en desuso en C ++ 17, surgieron algunas preocupaciones sobre la solución presentada en esta respuesta. Sin embargo, el comité de estándares de C ++ agregó una declaración importante en http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html diciendo
este componente de la biblioteca debe retirarse del Anexo D, junto a él, hasta que se estandarice un reemplazo adecuado.
Entonces, en el futuro previsible, la codecvtsolución en esta respuesta es segura y portátil.
Esto solo funciona si todos los caracteres son de un solo byte, es decir, ASCII o ISO-8859-1 . Cualquier cosa de varios bytes fallará miserablemente, incluido UTF-8. La pregunta contiene claramente caracteres de varios bytes.
Mark Ransom
28
Esta respuesta es claramente insuficiente y no hace nada más que copiar caracteres estrechos tal como está en caracteres anchos. Vea las otras respuestas, particularmente la de Johann Gerell, para saber cómo pasar de una cadena codificada de múltiples bytes o utf8 a una cadena de caracteres utf16.
DLRdave
10
Esta respuesta es peligrosa y probablemente se romperá en un sistema que no sea ASCII. es decir, este nombre pirateará un nombre de archivo árabe.
Stephen
9
Esta respuesta es útil si ignora los matices del cuerpo de la pregunta y se enfoca en el título de la pregunta, que es lo que me trajo aquí de Google. Tal como está, el título de la pregunta es extremadamente engañoso y debe modificarse para reflejar la verdadera pregunta que se hace
Anne Quinn,
3
Esto funciona solo para caracteres ASCII de 7 bits. Para latin1, funciona solo si char está configurado como unsigned. Si el tipo char está firmado (que suele ser el caso), los caracteres> 127 darán resultados incorrectos.
huyc
32
Su pregunta no está especificada. Estrictamente, ese ejemplo es un error de sintaxis. Sin embargo, std::mbstowcses probablemente lo que estás buscando.
Es una función de biblioteca C y funciona en buffers, pero aquí hay un modismo fácil de usar, cortesía de TBohne (anteriormente 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: debe asegurarse de que la codificación en tiempo de ejecución sea la misma que la codificación en tiempo de compilación. Es posible que necesite setlocaleo ajuste los indicadores del compilador. No lo sé porque no uso Windows, pero es por eso que no es una característica común. Considere la otra respuesta si es posible.
@WaffleSouffle Eso está desactualizado. Se han requerido implementaciones contiguas desde 2011 y las implementaciones abandonaron dichos trucos mucho antes de eso.
Potatoswatter
1
y algunos entornos como mingw todavía no tienen el encabezado codecvt, por lo que algunas de las 'mejores' soluciones anteriores no funcionan, lo que significa que este problema todavía no tiene buenas soluciones en mingw, incluso a partir de diciembre de 2014
Brian Jack,
18
Solo API de Windows, implementación previa a C ++ 11, en caso de que alguien lo necesite:
Puedes optimizarlo. No hay necesidad de hacer una doble copia de la cadena usando a vector. Simplemente reservar los caracteres de la cadena haciendo wstring strW(charsNeeded + 1);y luego usarlo como memoria intermedia para la conversión: &strW[0]. Por último, asegúrese de que el último nulo esté presente después de la conversión haciendostrW[charsNeeded] = 0;
c00000fd
1
@ c00000fd, que yo sepa, el buffer interno std :: basic_string debe ser continuo solo desde el estándar C ++ 11. Mi código es pre C ++ 11, como se indica en la parte superior de la publicación. Por lo tanto, el código & strW [0] no sería estándar y podría bloquearse legítimamente en tiempo de ejecución.
Alex Che
13
Si está utilizando Windows / Visual Studio y necesita convertir una cadena a wstring, puede usar:
#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());
El mismo procedimiento para convertir un wstring a cadena (a veces necesitará especificar una página de códigos ):
#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);}
A veces necesitará deshabilitar la advertencia de seguridad # 4995 ', no sé de otra solución (para mí sucede cuando compilé para Windows XP en VS2012).
Lo siento, no soy un hablante nativo de inglés. Edite como mejor le parezca.
lmiguelmh
¿Qué pasa con el votante? ¿Qué hay de malo en la respuesta?
lmiguelmh
Probablemente el hecho de que promueve código no portátil.
Pavel Minaev
Sí, por eso dije que esto solo funciona en Windows / Visual Studio. Pero al menos esta solución es correcta, y no esta:char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
lmiguelmh
Nota adicional: CA2W está bajo el espacio de nombres de ATL. (ATL :: CA2W)
Val
12
Aquí hay una forma de combinar string, wstringy constantes de cadena mixtas para wstring. Usa la wstringstreamclase.
Esto NO funciona para codificaciones de caracteres de varios bytes. Esta es solo una manera tonta de desechar la seguridad de tipos y expandir caracteres de 7 bits desde std :: string a los 7 bits inferiores de cada carácter de std: wstring. Esto solo es útil si tiene cadenas ASCII de 7 bits y necesita llamar a una API que requiere cadenas anchas.
La respuesta parece interesante. ¿Podría explicar un poco: esto funcionará para codificaciones de varios bytes y por qué / cómo?
wh1t3cat1k
Los esquemas de codificación son ortogonales a la clase de almacenamiento. stringalmacena caracteres de 1 byte y wstringalmacena 2 caracteres de byte. algo así como utf8 almacena caracteres de mulitbytes como una serie de valores de 1 byte, es decir, en a string. Las clases de cadena no ayudan con la codificación. No soy un experto en codificar clases en c ++.
Mark Lakata
2
¿Alguna razón por la cual esta no es la mejor respuesta, dado lo breve y simple que es? ¿Algún caso que no cubra?
Ryuu
@ MarkLakata, leí tu respuesta al primer comentario pero todavía no estoy seguro. ¿Funcionará para caracteres de varios bytes? En otras palabras, ¿no es propenso a la misma trampa que esta respuesta ?
Marc.2377
@ Marc.2377 Esto NO funciona para codificaciones de caracteres de varios bytes. Esta es solo una manera tonta de desechar la seguridad de tipo y expandir caracteres de 7 bits std::stringhacia los 7 bits inferiores de cada carácter de std:wstring. Esto solo es útil si tiene cadenas ASCII de 7 bits y necesita llamar a una API que requiere cadenas anchas. Mire stackoverflow.com/a/8969776/3258851 si necesita algo más sofisticado.
Porque esto solo funciona si la codificación es Windows-1252, que ni siquiera puede contener las letras de la pregunta.
Mooing Duck
3
esta es la forma de hacerlo menos propensa a errores, cuando sabes que estás tratando con ASCII. Lo cual es un caso de uso prominente al portar aplicaciones a las API más nuevas.
Sid Sarasvati
Este no es el camino. Si está utilizando Visual Studio, debe usarlo atlconv.h. Verifica las otras respuestas.
Esta variante es mi favorita en la vida real. Convierte la entrada, si es válida UTF-8, a la respectiva wstring. Si la entrada está dañada, wstringse construye a partir de los bytes individuales. Esto es extremadamente útil si realmente no puede estar seguro de la calidad de sus datos de entrada.
¿Qué sucede con todas estas respuestas asignando memoria dinámica de una manera insegura y luego copiando los datos del búfer a la cadena? ¿Por qué nadie se deshace del intermediario inseguro?
Mooing Duck
jajakubile, ¿puedes ayudarme con algo similar para ws2s?
cristian
1
Según mis propias pruebas (en Windows 8, vs2010), mbstowcs puede dañar la cadena original, solo funciona con la página de códigos ANSI. Si MultiByteToWideChar / WideCharToMultiByte también puede causar daños en la cadena, pero tienden a reemplazar los caracteres que no conocen con '?' los signos de interrogación, pero mbstowcs tiende a detenerse cuando encuentra caracteres desconocidos y corta cadenas en ese mismo punto. (He probado caracteres vietnamitas en ventanas finlandesas).
Por lo tanto, prefiera la función Multi * -windows api sobre las funciones analógicas ansi C.
Además, lo que he notado de la manera más corta para codificar cadenas de una página de códigos a otra no es usar llamadas de función api MultiByteToWideChar / WideCharToMultiByte sino sus macros analógicas ATL: W2A / A2W.
Entonces, la función analógica como se mencionó anteriormente sonaría así:
Pero tenga en cuenta que esas macros usan mucho stack - no las use para bucles o bucles recursivos para la misma función - después de usar la macro W2A o A2W - mejor devolver ASAP, por lo que la pila se liberará de la conversión temporal.
Este Str2Wstr tiene un problema con la terminación 0. Ya no es posible concatenar las cadenas w generadas a través de "+" (como en wstring s3 = s1 + s2). Pronto publicaré una respuesta para resolver este problema. Primero tiene que hacer algunas pruebas para detectar pérdidas de memoria.
Eso tampoco va a funcionar. Tendrá que convertir esos caracteres no BMP en secuencias de escape C.
Dave Van den Eynde
3
@Dave: funciona si su compilador admite unicode en los archivos fuente, y todos los de la última década lo hacen (visual studio, gcc, ...)
Thomas Bonini
Hola, independientemente de la codificación predeterminada del sistema (por ejemplo, puedo tener el árabe como mi codificación predeterminada del sistema), ¿cuál debería ser la codificación del archivo de código fuente para que funcione L "お は よ う"? ¿debería estar en UTF-16, o puedo tener UTF-8 sin BOM para la codificación del archivo .cpp?
Afriza N. Arief
2
@afriza: realmente no importa mientras su compilación lo admita
Thomas Bonini
2
No es un error; Los caracteres extendidos en una cadena "estrecha" se definen para mapear a secuencias multibyte. El compilador debe admitirlo siempre que el sistema operativo lo haga, que es lo mínimo que puede pedir.
Potatoswatter
-2
usa este código para convertir tu cadena a wstring
Tenga en cuenta que la pregunta no menciona a Windows y esta respuesta es solo para Windows.
Johann Gerell
CP_ACPEs sin duda el argumento equivocado. De repente, el estado del entorno del hilo en ejecución tiene un efecto en el comportamiento del código. No recomendable. Especifique una codificación de caracteres fija en su conversión. (Y considere los errores de manejo.)
strings
acepte caracteres de> 8 bits. ¿Ya está codificado en UTF-8?"おはよう"
una cadena codificada por el sistema?Respuestas:
Suponiendo que la cadena de entrada en su ejemplo (お は よ う) es una codificación UTF-8 (que no lo es, por lo que parece, pero supongamos que es por el bien de esta explicación :-)) representación de una cadena Unicode de su interés, entonces su problema puede resolverse completamente con la biblioteca estándar (C ++ 11 y más reciente) solo.
La versión TL; DR:
Ejemplo compilable y ejecutable en línea más largo:
(Todos muestran el mismo ejemplo. Hay muchos para la redundancia ...)
Nota (antigua) :
Como se señaló en los comentarios y se explicó en https://stackoverflow.com/a/17106065/6345, hay casos en que el uso de la biblioteca estándar para convertir entre UTF-8 y UTF-16 podría dar diferencias inesperadas en los resultados en diferentes plataformas . Para una mejor conversión, considere
std::codecvt_utf8
como se describe en http://en.cppreference.com/w/cpp/locale/codecvt_utf8Nota (nueva) :
Dado que el
codecvt
encabezado está en desuso en C ++ 17, surgieron algunas preocupaciones sobre la solución presentada en esta respuesta. Sin embargo, el comité de estándares de C ++ agregó una declaración importante en http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html diciendoEntonces, en el futuro previsible, la
codecvt
solución en esta respuesta es segura y portátil.fuente
std::codecvt_utf8
para principiantes?<codecvt>
está en desuso desde C ++ 17.fuente
Su pregunta no está especificada. Estrictamente, ese ejemplo es un error de sintaxis. Sin embargo,
std::mbstowcs
es probablemente lo que estás buscando.Es una función de biblioteca C y funciona en buffers, pero aquí hay un modismo fácil de usar, cortesía de TBohne (anteriormente Mooing Duck):
fuente
setlocale
o ajuste los indicadores del compilador. No lo sé porque no uso Windows, pero es por eso que no es una característica común. Considere la otra respuesta si es posible.std::string ws(s.size()); ws.resize(mbstowcs(&ws[0], s.c_str(), s.size());
RAII FTWSolo API de Windows, implementación previa a C ++ 11, en caso de que alguien lo necesite:
fuente
vector
. Simplemente reservar los caracteres de la cadena haciendowstring strW(charsNeeded + 1);
y luego usarlo como memoria intermedia para la conversión:&strW[0]
. Por último, asegúrese de que el último nulo esté presente después de la conversión haciendostrW[charsNeeded] = 0;
Si está utilizando Windows / Visual Studio y necesita convertir una cadena a wstring, puede usar:
El mismo procedimiento para convertir un wstring a cadena (a veces necesitará especificar una página de códigos ):
Puede especificar una página de códigos e incluso UTF8 (eso es bastante bueno cuando se trabaja con JNI / Java ). En esta respuesta se muestra una forma estándar de convertir un std :: wstring a utf8 std :: string .
Si desea saber más acerca de las páginas de códigos, hay un artículo interesante sobre Joel sobre software: el mínimo absoluto que todo desarrollador de software debe saber absolutamente, positivamente sobre Unicode y los conjuntos de caracteres .
Estas macros CA2W (Convertir Ansi a Wide = unicode) son parte de las macros de conversión de cadenas ATL y MFC , incluidos los ejemplos.
A veces necesitará deshabilitar la advertencia de seguridad # 4995 ', no sé de otra solución (para mí sucede cuando compilé para Windows XP en VS2012).
Editar: Bueno, de acuerdo con este artículo, el artículo de Joel parece ser: "aunque entretenido, es bastante ligero en detalles técnicos reales". Artículo: Lo que todo programador absolutamente necesita saber sobre la codificación y los juegos de caracteres para trabajar con texto .
fuente
char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
Aquí hay una forma de combinar
string
,wstring
y constantes de cadena mixtas parawstring
. Usa lawstringstream
clase.Esto NO funciona para codificaciones de caracteres de varios bytes. Esta es solo una manera tonta de desechar la seguridad de tipos y expandir caracteres de 7 bits desde std :: string a los 7 bits inferiores de cada carácter de std: wstring. Esto solo es útil si tiene cadenas ASCII de 7 bits y necesita llamar a una API que requiere cadenas anchas.
fuente
string
almacena caracteres de 1 byte ywstring
almacena 2 caracteres de byte. algo así como utf8 almacena caracteres de mulitbytes como una serie de valores de 1 byte, es decir, en astring
. Las clases de cadena no ayudan con la codificación. No soy un experto en codificar clases en c ++.std::string
hacia los 7 bits inferiores de cada carácter destd:wstring
. Esto solo es útil si tiene cadenas ASCII de 7 bits y necesita llamar a una API que requiere cadenas anchas. Mire stackoverflow.com/a/8969776/3258851 si necesita algo más sofisticado.De
char*
awstring
:De
string
awstring
:Tenga en cuenta que esto solo funciona bien si la cadena que se convierte contiene solo caracteres ASCII.
fuente
atlconv.h
. Verifica las otras respuestas.usando Boost.Locale:
fuente
Esta variante es mi favorita en la vida real. Convierte la entrada, si es válida UTF-8, a la respectiva
wstring
. Si la entrada está dañada,wstring
se construye a partir de los bytes individuales. Esto es extremadamente útil si realmente no puede estar seguro de la calidad de sus datos de entrada.fuente
Si tienes QT y eres flojo para implementar una función y otras cosas, puedes usar
std :: string str; QString (str) .toStdWString ()
fuente
QString
, porque elQString
constructor no puede aceptar una cadena por alguna razón.El método s2ws funciona bien. La esperanza ayuda.
fuente
Según mis propias pruebas (en Windows 8, vs2010), mbstowcs puede dañar la cadena original, solo funciona con la página de códigos ANSI. Si MultiByteToWideChar / WideCharToMultiByte también puede causar daños en la cadena, pero tienden a reemplazar los caracteres que no conocen con '?' los signos de interrogación, pero mbstowcs tiende a detenerse cuando encuentra caracteres desconocidos y corta cadenas en ese mismo punto. (He probado caracteres vietnamitas en ventanas finlandesas).
Por lo tanto, prefiera la función Multi * -windows api sobre las funciones analógicas ansi C.
Además, lo que he notado de la manera más corta para codificar cadenas de una página de códigos a otra no es usar llamadas de función api MultiByteToWideChar / WideCharToMultiByte sino sus macros analógicas ATL: W2A / A2W.
Entonces, la función analógica como se mencionó anteriormente sonaría así:
_acp se declara en la macro USES_CONVERSION.
O también la función que a menudo echo de menos al realizar una conversión de datos antigua a una nueva:
Pero tenga en cuenta que esas macros usan mucho stack - no las use para bucles o bucles recursivos para la misma función - después de usar la macro W2A o A2W - mejor devolver ASAP, por lo que la pila se liberará de la conversión temporal.
fuente
Cadena a wstring
wstring a String
fuente
string s = "おはよう";
es un errorDebe usar wstring directamente:
fuente
usa este código para convertir tu cadena a wstring
fuente
CP_ACP
Es sin duda el argumento equivocado. De repente, el estado del entorno del hilo en ejecución tiene un efecto en el comportamiento del código. No recomendable. Especifique una codificación de caracteres fija en su conversión. (Y considere los errores de manejo.)