Як перетворити wstring в рядок?


204

Питання в тому, як перетворити wstring в рядок?

Маю наступний приклад:

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

вихід із коментованим рядком:

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

але без тільки:

std::wstring =    Hello

Чи є щось неправильне в прикладі? Чи можу я виконати конверсію, як вище

EDIT

Новий приклад (з урахуванням деяких відповідей)

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

Вихід:

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

отже, струнний потік не можна використовувати для перетворення wstring у рядок.


4
Як ви можете задати це питання, не вказуючи також кодування?
Девід Геффернан

5
@tenfour: Навіщо std::wstringвзагалі використовувати ? stackoverflow.com/questions/1049947/…
dalle

11
@dalle Якщо у вас є дані, які вже закодовані в UTF-16, то чи UTF-16 вважається шкідливим, це суперечка. І для чого це варто, я не думаю, що будь-яка форма трансформації шкідлива; що шкідливо, це те, що люди думають, що розуміють Unicode, якщо насправді цього не роблять.
Девід Геффернан

2
Чи повинно це бути кросплатформене рішення?
ali_bahoo

2
Стандарт @dalle c ++ жодним чином не згадує utf (utf-8 або utf-16). Отримав посилання, де написано, чому utf-16 не може кодуватися wstring?
BЈович

Відповіді:


31

Ось розроблене рішення, засноване на інших пропозиціях:

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

Зазвичай це працює для Linux, але створить проблеми в Windows.


@Phillip: яка частина коду залежить від c-локалі? чи std::setlocale(LC_ALL, "");справді потрібно?
смерлін

2
використання std::wcout.imbue(locale)має виконувати цю роботу також, і це має перевагу, що воно не змінює жодного глобального стану.
смерлін

32
З std::wstring_convertC ++ 11 викликає багато цього шуму.
Cubbi

7
@Philipp, що ви маєте на увазі "створить проблеми в Windows"? Які проблеми?
Гілі

1
Наведений вище код дає (як скопійовано) дає мені *** glibc detected *** test: malloc(): smallbin double linked list corrupted: 0x000000000180ea30 ***64-розрядний Linux (gcc 4.7.3). Хтось ще відчував це?
hogliux

312

Як вказував Куббі в одному з коментарів, std::wstring_convert(C ++ 11) пропонує чітке просте рішення (потрібно #include <locale>і <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 );

Я використовував комбінацію wcstombsта виснажливе розподілення / розмежування пам’яті до того, як я натрапив на це.

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

оновлення (2013.11.28)

Один лайнер можна вказати так (Дякую Guss за ваш коментар):

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

Функції обгортки можна вказати так: (Дякую ArmanSchwarz за ваш коментар)

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

Примітка: є деякі суперечки про те string/ wstringповинно бути передані і функції як посилання або як літерали (з - за C ++ 11 і компілятор оновлень). Я залишу рішення особі, яка реалізує, але це варто знати.

Примітка. Я використовую std::codecvt_utf8наведений вище код, але якщо ви не використовуєте UTF-8, вам потрібно буде змінити це на відповідне кодування, яке ви використовуєте:

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


25
Будь ласка, +1 : це офіційний стандарт C ++ для перетворення рядків. Ви також можете використовувати from_bytes для перетворення в інший спосіб. Оскільки мені особисто подобаються однолінійки, ось моя версія:std::wstring str = std::wstring_convert<std::codecvt_utf<wchar_t>>().from_bytes("some string");
Guss

7
Схоже, що en.cppreference.com/w/cpp/header/codecvt станом на g ++ 4.8.2 недоступний. Два методи s2ws та ws2s наразі не працюють під Linux
Begui

5
Схоже, це застаріле ( stackoverflow.com/a/42946556/211176 ). Мій компілятор видає помилки, коли я намагаюся запустити цей код
adam_0


5
Для всіх, хто переживає C ++ 17 та подальшу сумісність (через застарілість), дивіться: stackoverflow.com/a/18597384/6205379
Timo

128

Рішення від: 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;

Остерігайся щоб тут взагалі не відбувається перетворення набору символів. Що це робить просто привласнити кожну ітерацію wchar_tдо char- усічення перетворення. Він використовує std :: string c'tor :

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

Як зазначено в коментарях:

значення 0-127 ідентичні практично в кожному кодуванні, тому обрізання значень, які всі менше 127, призводить до одного тексту. Поставте китайський символ, і ви побачите провал.

-

значення 128-255 кодової сторінки Windows 1252 (за замовчуванням для англійської мови Windows) та значення 128-255 унікоду здебільшого однакові, тому, якщо це кодова сторінка, яку ви використовуєте більшість із цих символів, слід обрізати правильні значення. (Я повністю очікував, що á і õ працювати, я знаю, що наш код на роботі покладається на це для é, що я скоро виправлю)

І зверніть увагу , що кодові точки в діапазоні 0x80 - 0x9Fв WIN1252 буде НЕ працювати. Це включає в себе , œ, ž, Ÿ, ...


2
Як не дивно, це працює у Visual Studio 10. Що відбувається? Це повинно викликати присвоєння обрізання від wchar_t до char для всіх елементів початкового рядка.
Pedro Lamarão

6
... коли мова йде про будь-які не латинські символи.
JavaRunner

8
@ PedroLamarão: значення 0-127 ідентичні практично у кожному кодуванні, тому усі обрізні значення, менші ніж 127, призводять до одного тексту. Поставте китайський символ, і ви побачите провал.
Mooing Duck

3
@ PedroLamarão: значення 128-255 кодової сторінки Windows 1252 (за замовчуванням для англійської мови Windows) та значення 128-255 унікоду здебільшого однакові, тому, якщо це кодова сторінка, яку ви використовуєте, більшість цих символів повинні бути усічені до правильних значення. (Я повністю очікував, що я і попрацюю, я знаю, що наш код на роботі покладається на це для é, що я незабаром
виправлю

2
Це чудово працює. MSVS 2015 та MSVS 2017 та MINGW / g ++ та clang ++. Легіт ++ 1.
Нікос

11

Замість того, щоб включати локалі та всі такі вигадливі речі, якщо ви знаєте для FACT, ваша струна є конвертованою, просто зробіть це:

#include <iostream>
#include <string>

using namespace std;

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

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

Живий приклад тут


2
+1, тому що це просте рішення, яке працює для деяких сценаріїв (я можу додати, для вільного визначення поняття "працює").
ворон

2
Практично те саме, що і рішення namar0x0309, яке є набагато більш елегантним IMHO. Але це тільки я.
onitake

Я накрутив ваш код, щоб насправді працювати з мінімальною модифікацією ;-)
rubenvb

9
-1 Якщо у вас в’язка, швидше за все, ви маєте справу з багатобайтовими символами. Якби ви могли знати, що струна є тривіально конвертованою, ви б не обробляли вкраплення в першу чергу. Швидше за все, ви маєте справу з іншою бібліотекою, яка розраховує на те, що ви правильно поводитеся з в'яззю. Обрізання wchars - це просто благання важко відстежити помилку. Також слід використовувати "string result (w.begin (), w.end ());" якщо ви збираєтеся це зробити, щоб уникнути циклу, який може викликати багато перерозподілу.
Кіан

7

Я вважаю, що офіційним способом все-таки є проникнення codecvtграней (потрібен якийсь переклад, відомий для місцевого значення), як у

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

або щось подібне, у мене немає робочого коду, який лежить навколо. Але я не впевнений, скільки людей в цей час користується цією технікою, а скільки просто просять покажчики пам’яті та дозволяють ICU чи якійсь іншій бібліотеці обробляти деталі горі.


7

З кодом є дві проблеми:

  1. Перетворення в const std::string s( ws.begin(), ws.end() ); не потрібно для правильного відображення широких символів на їх вузький аналог. Швидше за все, кожен широкий персонаж буде просто набраний char.
    Вирішення цієї проблеми вже дано у відповіді kem і передбачає narrowфункцію ctypeграні локалу .

  2. Ви пишете вихід std::coutі std::wcoutв одну і ту ж програму. Обидва coutі wcoutпов'язані з одним і тим же потоком ( stdout), і результати використання одного і того ж потоку як байтово орієнтованого потоку (як coutі) і широкоорієнтованого потоку (як wcoutі) не визначені.
    Найкращий варіант - уникнути змішування вузького та широкого вихідного сигналу до одного (нижнього) потоку. Для stdout/ cout/ wcoutви можете спробувати переключити орієнтацію stdoutпри перемиканні між широким і вузьким виходом (або навпаки):

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

Так, це вирішує проблему із використанням cout та wcout.
BЈоviћ

7

Кодування за замовчуванням увімкнено:

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

Цей код має дві форми для перетворення std :: string в std :: wstring і std :: wstring в std :: string. Якщо ви заперечите #if, визначений WIN32, ви отримаєте той самий результат.

1. std :: рядок до 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 to 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. У Windows потрібно надрукувати unicode, використовуючи 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. За основною програмою.

#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. Нарешті, вам потрібна потужна і повна підтримка символів Unicode в консолі. Я рекомендую ConEmu і встановити як термінал за замовчуванням у Windows . Вам потрібно підключити Visual Studio до ConEmu. Пам'ятайте, що файл exe програми Visual Studio - це devenv.exe

Тестовано на Visual Studio 2017 з VC ++; std = c ++ 17.

Результат

Результат1


6

Можна також просто використовувати вузький метод фасону ctype:

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

вбудований std :: рядок вузький (std :: wstring const & text)
{
    std :: locale const loc ("");
    wchar_t const * from = text.c_str ();
    std :: size_t const len ​​= text.size ();
    std :: вектор <char> буфер (len + 1);
    std :: use_facet <std :: ctype <wchar_t>> (loc) .narrow (від, з + len, '_' та буфер [0]);
    return std :: string (& buffer [0], & buffer [len]);
}

6

На момент написання цієї відповіді Google номер 1, який шукає "конвертувати рядок в'язання", розташував вас на цій сторінці. Моя відповідь показує, як перетворити рядок у wstring, хоча це НЕ актуальне питання, і я, мабуть, повинен видалити цю відповідь, але це вважається поганою формою. Можливо, ви захочете перейти до цієї відповіді StackOverflow , яка зараз займає більш високий рейтинг, ніж ця сторінка.


Ось спосіб поєднання струнних, wstring та змішаних рядкових констант до wstring. Використовуйте клас 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();

13
Це не прив'язка до перетворення рядків
poitroae

1
@Michael Чи можете ви поясніть, будь ласка? Що з цього приводу невірно? Ваш коментар не корисний без додаткових деталей.
Нейт

1
це рядок до wstring перетворення. тобто протилежне питанню.
Джефф МакКлінток

4

Крім перетворення типів, слід також знати про фактичний формат рядка.

Під час компіляції для багатобайтних наборів символів Visual Studio і Win API передбачає UTF8 (фактично кодування Windows, що є Windows-28591 ).
При компілюванні для Unicode Character set Visual studio і Win API передбачає UTF16.

Отже, ви також повинні перетворити рядок з UTF16 в формат UTF8, а не просто перетворити в std :: string.
Це стане необхідним при роботі з різними символами, як деякі не латинські мови.

Ідея полягає у тому, щоб вирішити, що std::wstring завжди являє собою UTF16 .
І std::string завжди представляє UTF8 .

Це не виконує компілятор, це більше корисна політика. Зверніть увагу на строкові префікси, які я використовую для визначення UTF16 ( L ) та UTF8 ( u8 ).

Для перетворення між двома типами слід використовувати: 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;
}

3

У моєму випадку я повинен використовувати багатобайтовий символ (MBCS), і я хочу використовувати std :: string та std :: wstring. І не можу використовувати c ++ 11. Тому я використовую mbstowcs та wcstombs.

Я виконую ту саму функцію з використанням new, delete [], але це повільніше, ніж це.

Це може допомогти Як: Перетворити між різними типами рядків

EDIT

Однак у випадку перетворення в wstring та вихідний рядок немає алфавіту та багатобайтового рядка, він не працює. Тому я змінюю wcstombs на 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, щоб використовувати "MultiByteToWideChar" замість "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);
}

Як я можу використовувати "wcstombs_s" з gcc 4.8? Тому що я бачу, що це C ++ 11 особливість.
Крістіан

@cristian Ви можете використовувати "небезпечну" версію цієї функції wcstombs().
Vizor

3

Це рішення надихається в рішенні dk123 , але використовує залежно від локалі кодексу. Результат знаходиться в кодованій мовою рядку замість UTF-8 (якщо вона не встановлена ​​як локаль):

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

Я шукав його, але не можу його знайти. Нарешті я виявив, що я можу отримати правильну грань std::localeза допомогою std::use_facet()функції з правильним іменем типу. Сподіваюсь, це допомагає.


Vizor, які переваги (якщо такі є) перетворення з залежною від локалі фацетою?
Марк.2377

Якщо ви працюєте з рядками з системи, наприклад з консольного введення.
Vizor

1

У разі, якщо хтось інший зацікавлений: мені потрібен клас, який можна було б взаємозамінно використовувати там, де stringабо wstringбуло очікувано. Наступний клас convertible_string, заснований на вирішенні dk123 ігрових , може бути инициализирован або string, char const*, wstringабо wchar_t const*і може бути призначений на або неявно перетворити або в stringабо wstring(так можна передати у функцію , які приймають або).

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

1
Я вважаю за краще зберігати std::wstringв класі, ніж зберігати std::stringта робити перетворення, std::wstringколи потрібно, щоб отримати std::wstring. Бо std::wstringдещо швидше std::stringі краще сумісне. Навіть вона споживає більше пам’яті, ніж 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); }

-1

Я використовую нижче, щоб перетворити wstring в рядок.

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;

Здається, вам не вистачає стандартного заголовка ( <string>) та визначення для WideCharToMultiByte()- це якась обгортка навколо 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"

3
поясніть, будь ласка, що у вашій відповіді робить
уре

1
Звідки береться функція UTF8string?
Жан-Крістоф Бланшард
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.