¿Cómo convertir wstring en cadena?

204

La pregunta es cómo convertir wstring en cadena.

Tengo el siguiente ejemplo:

#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;
}

El resultado con la línea comentada es:

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

pero sin es solo:

std::wstring =    Hello

¿Hay algo malo en el ejemplo? ¿Puedo hacer la conversión como arriba?

EDITAR

Nuevo ejemplo (teniendo en cuenta algunas respuestas) es

#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;
}

El resultado es:

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

por lo tanto, el flujo de cadena no se puede usar para convertir wstring en cadena.

BЈовић
fuente
44
¿Cómo puede hacer esta pregunta sin especificar también las codificaciones?
David Heffernan el
55
@tenfour: ¿Por qué usarlo std::wstring? stackoverflow.com/questions/1049947/…
dalle
11
@dalle Si tiene datos que ya están codificados con UTF-16, si UTF-16 se considera dañino es algo discutible. Y por lo que vale, no creo que ninguna forma de transformación sea dañina; lo que es dañino es que las personas piensan que entienden Unicode cuando en realidad no lo hacen.
David Heffernan el
2
¿Tiene que ser una solución multiplataforma?
ali_bahoo
2
@dalle c ++ standard no menciona utf de ninguna manera (utf-8 o utf-16). ¿Tienes un enlace donde dice por qué utf-16 no puede codificarse con wstring?
B 26овић

Respuestas:

31

Aquí hay una solución resuelta basada en las otras sugerencias:

#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;
  }
}

Esto generalmente funcionará para Linux, pero creará problemas en Windows.

Philipp
fuente
@Phillip: ¿qué parte del código depende de la configuración regional c? ¿Es std::setlocale(LC_ALL, "");realmente necesario?
smerlin
2
el uso también std::wcout.imbue(locale)debería hacer el trabajo, y tiene la ventaja de que no cambia ningún estado global.
smerlin
32
El std::wstring_convertde C ++ 11 envuelve mucho de este ruido.
Cubbi
77
@Philipp, ¿qué quieres decir con "creará problemas en Windows"? ¿Qué tipo de problemas?
Gili
1
El código anterior da (como se copió) me da un *** glibc detected *** test: malloc(): smallbin double linked list corrupted: 0x000000000180ea30 ***Linux en 64 bits (gcc 4.7.3). ¿Alguien más está experimentando esto?
hogliux
312

Como Cubbi señaló en uno de los comentarios, std::wstring_convert(C ++ 11) proporciona una solución simple y ordenada (necesita #include <locale>y <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 );

Estaba usando una combinación de wcstombstediosa asignación / desasignación de memoria antes de encontrar esto.

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

actualizar (2013.11.28)

Uno de los revestimientos puede expresarse así (Gracias Guss por tu comentario):

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

Las funciones del contenedor se pueden establecer de la siguiente manera: (Gracias ArmanSchwarz por tu comentario)

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);
}

Nota: existe cierta controversia sobre si string/ wstringdebería pasarse a las funciones como referencias o como literales (debido a C ++ 11 y las actualizaciones del compilador). Dejaré la decisión a la persona que implementa, pero vale la pena saberlo.

Nota: Estoy usando std::codecvt_utf8el código anterior, pero si no está usando UTF-8, deberá cambiarlo a la codificación apropiada que está usando:

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

dk123
fuente
25
Por favor, haga +1 : esta es la forma estándar oficial de C ++ de hacer la conversión de cadenas. También puede usar from_bytes para convertir a la inversa. Porque personalmente me gustan las frases sencillas, aquí está mi versión:std::wstring str = std::wstring_convert<std::codecvt_utf<wchar_t>>().from_bytes("some string");
Guss
77
Parece que en.cppreference.com/w/cpp/header/codecvt no está disponible a partir de g ++ 4.8.2. Los dos métodos s2ws y ws2s no funcionan actualmente en Linux
Begui
55
Parece que esto está en desuso ( stackoverflow.com/a/42946556/211176 ). Mi compilador arroja errores cuando intento ejecutar este código
adam_0
55
Para cualquiera que se preocupe por C ++ 17 y una mayor compatibilidad (debido a la desuso), consulte: stackoverflow.com/a/18597384/6205379
Timo
128

Solución 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;

Tenga en cuenta que no hay conversión de juego de caracteres aquí en absoluto. Lo que esto hace es simplemente asignar cada iterado wchar_ta una charconversión truncada. Utiliza el std :: string c'tor :

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

Como se indica en los comentarios:

los valores 0-127 son idénticos en prácticamente todas las codificaciones, por lo que truncar valores que son todos menores que 127 da como resultado el mismo texto. Ponga un carácter chino y verá el fracaso.

-

los valores 128-255 de la página de códigos de Windows 1252 (el valor predeterminado de inglés de Windows) y los valores 128-255 de Unicode son en su mayoría los mismos, por lo que si esa es la página de códigos que está utilizando, la mayoría de esos caracteres deberían truncarse a los valores correctos. (Esperaba totalmente que á y õ funcionen, sé que nuestro código en el trabajo depende de esto para é, que pronto arreglaré)

Y tenga en cuenta que los puntos de código en el rango 0x80 - 0x9Fde Win1252 serán no trabajar. Esto incluye , œ, ž, Ÿ, ...

namar0x0309
fuente
2
Curiosamente, esto funciona en Visual Studio 10. ¿Qué está pasando? Esto debería causar una asignación truncada de wchar_t a char para todos los elementos de la cadena original.
Pedro Lamarão
66
... cuando se trata de caracteres no latinos.
JavaRunner
8
@ PedroLamarão: los valores 0-127 son idénticos en prácticamente todas las codificaciones, por lo que truncar valores que son todos menores que 127 da como resultado el mismo texto. Ponga un carácter chino y verá el fracaso.
Mooing Duck
3
@ PedroLamarão: los valores 128-255 de la página de códigos de Windows 1252 (el valor predeterminado de inglés de Windows) y los valores 128-255 de Unicode son en su mayoría los mismos, por lo que si esa es la página de códigos que está utilizando, la mayoría de esos caracteres deberían truncarse al correcto valores. (Esperaba totalmente que á y õ funcionen, sé que nuestro código en el trabajo depende de esto para é, que pronto arreglaré)
Mooing Duck
2
Esto funciona muy bien. MSVS 2015 y MSVS 2017 y MINGW / g ++ y clang ++. Legit ++ 1.
Nikos
11

En lugar de incluir la configuración regional y todas esas cosas elegantes, si sabe para HECHO que su cadena es convertible, simplemente haga esto:

#include <iostream>
#include <string>

using namespace std;

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

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

Ejemplo en vivo aquí

rubenvb
fuente
2
+1 porque es una solución simple que funciona para algunos escenarios (para una definición poco precisa de "funciona", podría agregar).
cuervo
2
Casi lo mismo que la solución de namar0x0309, que es mucho más elegante en mi humilde opinión. Pero solo soy yo.
onitake
Esculpí tu código para que realmente funcione con una modificación mínima ;-)
rubenvb
9
-1 Si tienes una wstring, es probable que estés lidiando con caracteres multibyte. Si pudieras saber que la cadena es trivialmente convertible, no estarías manejando un wstring en primer lugar. Lo más probable es que esté lidiando con otra biblioteca que espera que maneje el wstring correctamente. Truncar los wchars es solo pedir un error difícil de rastrear más adelante. Además, debe usar "string result (w.begin (), w.end ());" si fuera a hacerlo, para evitar un bucle que podría desencadenar muchas reasignaciones.
Kian
7

Creo que la forma oficial aún es ir por las codecvtfacetas (necesita algún tipo de traducción local), como en

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

o algo así, no tengo código de trabajo por ahí. Pero no estoy seguro de cuántas personas en estos días usan esa maquinaria y cuántas simplemente piden punteros a la memoria y dejan que la UCI o alguna otra biblioteca maneje los detalles sangrientos.

Christopher Creutzig
fuente
7

Hay dos problemas con el código:

  1. La conversión en const std::string s( ws.begin(), ws.end() );no es necesaria para asignar correctamente los caracteres anchos a su contraparte estrecha. Lo más probable es que cada carácter ancho solo sea encasillado char.
    La solución a este problema ya está dada en la respuesta de kem e involucra la narrowfunción de la ctypefaceta de la localidad .

  2. Está escribiendo resultados para ambos std::couty std::wcouten el mismo programa. Ambos couty wcoutestán asociados con el mismo flujo ( stdout) y los resultados de usar el mismo flujo tanto como flujo orientado a bytes (como lo couthace) y un flujo orientado a ancho (como lo wcouthace) no están definidos.
    La mejor opción es evitar mezclar salidas estrechas y anchas en la misma secuencia (subyacente). Para stdout/ cout/ wcout, puede intentar cambiar la orientación de stdoutcuando cambie entre salida ancha y angosta (o viceversa):

    #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
fuente
Sí, eso soluciona el problema con el uso de cout y wcout.
B 26овић
7

Codificación predeterminada en:

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

Este código tiene dos formas de convertir std :: string a std :: wstring y std :: wstring a std :: string. Si niega #if definió WIN32, obtendrá el mismo resultado.

1. std :: cadena a 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 a 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. En Windows necesita imprimir unicode, usando 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. En el programa 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. Finalmente, necesita un soporte potente y completo para caracteres unicode en la consola. Recomiendo ConEmu y establecerlo como terminal predeterminado en Windows . Necesita conectar Visual Studio a ConEmu. Recuerde que el archivo exe de Visual Studio es devenv.exe

Probado en Visual Studio 2017 con VC ++; std = c ++ 17.

Resultado

Resultado1

Joma
fuente
6

También podría usar el método estrecho de la faceta ctype directamente:

#include <clocale>
#include <locale>
#include <cadena>
#include <vector>

en línea std :: string estrecho (std :: wstring const y texto)
{
    std :: locale const loc ("");
    wchar_t const * from = text.c_str ();
    std :: size_t const len ​​= text.size ();
    std :: vector <char> buffer (len + 1);
    std :: use_facet <std :: ctype <wchar_t>> (loc) .narrow (from, from + len, '_', & buffer [0]);
    return std :: string (& buffer [0], & buffer [len]);
}
legalizar
fuente
6

Al momento de escribir esta respuesta, la búsqueda número uno de Google para "convertir string wstring" lo llevaría a esta página. Mi respuesta muestra cómo convertir una cadena a wstring, aunque esta NO es la pregunta real, y probablemente debería eliminar esta respuesta, pero se considera una mala forma. Es posible que desee saltar a esta respuesta de StackOverflow , que ahora está mejor clasificada que esta página.


Aquí hay una manera de combinar cadenas, wstring y constantes de cadenas mixtas para wstring. Use la clase 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
fuente
13
Esta no es una conversión de wstring a string
poitroae
1
@Michael ¿Puedes explicarlo? ¿Qué pasa con esto es incorrecto? Su comentario no es útil sin más detalles.
Nate
1
Esta es una conversión de cadena a wstring. es decir, lo contrario de la pregunta.
Jeff McClintock
4

Además de solo convertir los tipos, también debe tener en cuenta el formato real de la cadena.

Al compilar para el juego de caracteres Multi-byte Visual Studio y la API Win asume UTF8 (en realidad, la codificación de Windows es Windows-28591 ).
Al compilar para Unicode Character set Visual studio y Win API asume UTF16.

Por lo tanto, debe convertir la cadena de UTF16 a UTF8 también, y no solo convertir a std :: string.
Esto será necesario cuando trabaje con formatos de varios caracteres como algunos idiomas no latinos.

La idea es decidir que std::wstring siempre representa UTF16 .
Y std::string siempre representa UTF8 .

El compilador no aplica esto, es más una buena política. Tenga en cuenta los prefijos de cadena que uso para definir UTF16 ( L ) y UTF8 ( u8 ).

Para convertir entre los 2 tipos, debe usar: 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
fuente
3

En mi caso, tengo que usar caracteres multibyte (MBCS), y quiero usar std :: string y std :: wstring. Y no puede usar c ++ 11. Entonces uso mbstowcs y wcstombs.

Realizo la misma función con el uso de new, delete [], pero es más lento que esto.

Esto puede ayudar Cómo: Convertir entre varios tipos de cadenas

EDITAR

Sin embargo, en caso de convertir a wstring y la cadena de origen no es una cadena de alfabeto y de varios bytes, no funciona. Entonces cambio wcstombs a 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);
}

EDITAR para usar 'MultiByteToWideChar' en lugar 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);
}
heon
fuente
¿Cómo puedo usar "wcstombs_s" con gcc 4.8? Porque veo que es la función C ++ 11.
cristian
@cristian Puede usar la versión "insegura" de esta función wcstombs().
Vizor
3

Esta solución está inspirada en la solución de dk123 , pero utiliza una faceta codecvt dependiente de la configuración regional. El resultado está en una cadena codificada en la configuración regional en lugar de UTF-8 (si no se establece como configuración regional):

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);
}

Lo estaba buscando, pero no lo encuentro. Finalmente descubrí que puedo obtener la faceta correcta al std::localeusar la std::use_facet()función con el nombre de tipo correcto. Espero que esto ayude.

Visera
fuente
Vizor, ¿cuáles son las ventajas (si las hay) de convertir con la faceta dependiente de la configuración regional?
Marc.2377
Si trabaja con cadenas del sistema, desde la entrada de la consola, por ejemplo.
Vizor
1

En caso de que alguien más esté interesado: necesitaba una clase que se pudiera usar indistintamente donde sea que se esperara stringo wstring. La siguiente clase convertible_string, basado en la solución de dk123 , se puede inicializar con ya sea una string, char const*, wstringo wchar_t const*y puede ser asignado a por o implícitamente convierte en ya sea una stringo wstring(lo que puede ser pasado a un funciones que toman tampoco).

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
fuente
1
Prefiero almacenar un std::wstringen la clase, que almacenar std::stringy hacer una conversión std::wstringcuando sea necesario para obtener un std::wstring. Porque std::wstringes algo más rápido que std::stringy es mejor compatible. Incluso consume más memoria 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); }
profundo125
fuente
-1

Estoy usando a continuación para convertir wstring en cadena.

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
fuente
Parece que le falta un encabezado estándar ( <string>) y una definición de WideCharToMultiByte(): ¿es eso algo envolvente 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
fuente
3
Por favor explique lo Ure haciendo allí en su respuesta, de lo contrario puede obtener deletet
CodeFanatic
1
¿De dónde viene la función UTF8string?
Jean-Christophe Blanchard