Bagaimana cara mengubah wstring menjadi string?

204

Pertanyaannya adalah bagaimana cara mengkonversi wstring ke string?

Saya punya contoh berikut:

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

output dengan garis komentar adalah:

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

tetapi tanpa hanya:

std::wstring =    Hello

Apakah ada yang salah dalam contoh? Bisakah saya melakukan konversi seperti di atas?

EDIT

Contoh baru (dengan mempertimbangkan beberapa jawaban) adalah

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

Outputnya adalah:

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

oleh karena itu stringstream tidak dapat digunakan untuk mengubah wstring menjadi string.

BЈовић
sumber
4
Bagaimana Anda bisa mengajukan pertanyaan ini tanpa menentukan juga pengkodeannya?
David Heffernan
5
@tenfour: Mengapa menggunakan std::wstringsama sekali? stackoverflow.com/questions/1049947/…
dalle
11
@dalle Jika Anda memiliki data yang sudah disandikan dengan UTF-16, apakah UTF-16 dianggap berbahaya atau tidak, agak diperdebatkan. Dan untuk apa nilainya, saya tidak berpikir bentuk transformasi apa pun berbahaya; apa yang berbahaya adalah orang berpikir mereka mengerti Unicode padahal sebenarnya mereka tidak.
David Heffernan
2
Apakah itu harus menjadi solusi lintas platform?
ali_bahoo
2
@dalle c ++ standar tidak menyebutkan utf dengan cara apa pun (utf-8 atau utf-16). Punya tautan di mana dikatakan mengapa utf-16 tidak dapat dikodekan dengan wstring?
BЈовић

Jawaban:

31

Berikut adalah solusi yang berhasil berdasarkan saran lainnya:

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

Ini biasanya bekerja untuk Linux, tetapi akan menimbulkan masalah pada Windows.

Philipp
sumber
@Phillip: bagian mana dari kode yang bergantung pada c-locale? apakah yang std::setlocale(LC_ALL, "");benar - benar dibutuhkan?
smerlin
2
menggunakan std::wcout.imbue(locale)harus melakukan pekerjaan itu juga, dan memiliki manfaat bahwa itu tidak mengubah keadaan global.
smerlin
32
The std::wstring_convertdari C ++ 11 merangkum banyak kebisingan ini.
Cubbi
7
@ Pilip, apa maksudmu "akan membuat masalah pada Windows"? Masalah apa?
Gili
1
Kode di atas memberi (seperti disalin) memberi saya *** glibc detected *** test: malloc(): smallbin double linked list corrupted: 0x000000000180ea30 ***di linux 64-bit (gcc 4.7.3). Adakah yang mengalami hal ini?
hogliux
312

Seperti yang ditunjukkan Cubbi dalam salah satu komentar, std::wstring_convert(C ++ 11) memberikan solusi sederhana yang rapi (Anda perlu #include <locale>dan <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 );

Saya menggunakan kombinasi dari wcstombsdan alokasi / dealokasi memori yang membosankan sebelum saya menemukan ini.

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

pembaruan (2013.11.28)

Satu liner dapat dinyatakan demikian (Terima kasih, Guss atas komentar Anda):

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

Fungsi Wrapper dapat dinyatakan sebagai: (Terima kasih ArmanSchwarz atas komentar Anda)

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

Catatan: ada beberapa kontroversi tentang apakah string/ wstringharus diteruskan ke fungsi sebagai referensi atau sebagai literal (karena C ++ 11 dan pembaruan kompiler). Saya akan menyerahkan keputusan kepada orang yang menerapkan, tetapi perlu diketahui.

Catatan: Saya menggunakan std::codecvt_utf8dalam kode di atas, tetapi jika Anda tidak menggunakan UTF-8 Anda harus mengubahnya ke pengkodean yang sesuai yang Anda gunakan:

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

dk123
sumber
25
Beri +1 : ini adalah cara standar C ++ resmi untuk melakukan konversi string. Anda juga dapat menggunakan from_bytes untuk mengonversi cara lain. Karena saya pribadi suka one-liners, ini versi saya:std::wstring str = std::wstring_convert<std::codecvt_utf<wchar_t>>().from_bytes("some string");
Guss
7
Sepertinya en.cppreference.com/w/cpp/header/codecvt tidak tersedia pada g ++ 4.8.2. Kedua metode s2ws dan ws2s saat ini tidak berfungsi di linux
Begui
5
Sepertinya ini sudah usang ( stackoverflow.com/a/42946556/211176 ). Kompiler saya melempar kesalahan ketika saya mencoba menjalankan kode ini
adam_0
5
Untuk siapa pun yang khawatir tentang C ++ 17 dan kompatibilitas lebih lanjut (karena penghentian) lihat: stackoverflow.com/a/18597384/6205379
Timo
128

Solusi dari: 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;

Berhati - hatilah karena tidak ada konversi rangkaian karakter yang terjadi di sini. Apa yang dilakukan adalah hanya untuk menetapkan setiap iterasi wchar_tke char- konversi terpotong. Ia menggunakan std :: string c'tor :

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

Sebagaimana dinyatakan dalam komentar:

nilai 0-127 identik di hampir setiap pengkodean, jadi memotong nilai yang semuanya kurang dari 127 hasil dalam teks yang sama. Masukkan karakter Cina dan Anda akan melihat kegagalannya.

-

nilai 128-255 dari windows codepage 1252 (standar Windows English) dan nilai 128-255 dari unicode sebagian besar sama, jadi jika itu codepage yang Anda gunakan sebagian besar karakter tersebut harus dipotong ke nilai yang benar. (Saya benar-benar berharap á dan õ berfungsi, saya tahu kode kami di tempat kerja mengandalkan ini untuk é, yang akan segera saya perbaiki)

Dan perhatikan bahwa titik kode dalam kisaran 0x80 - 0x9Fdi Win1252 tidak akan berfungsi. Ini termasuk , œ, ž, Ÿ, ...

namar0x0309
sumber
2
Anehnya, ini bekerja pada Visual Studio 10. Apa yang terjadi? Ini harus menyebabkan pemutusan truncating dari wchar_t untuk char untuk semua elemen string asli.
Pedro Lamarão
6
... ketika masuk ke karakter non-latin.
JavaRunner
8
@ PedroLamarão: nilai 0-127 identik di hampir setiap penyandian, jadi nilai pemotongan yang semuanya kurang dari 127 menghasilkan teks yang sama. Masukkan karakter Cina dan Anda akan melihat kegagalannya.
Mooing Duck
3
@ PedroLamarão: nilai 128-255 dari codepage windows 1252 (default Windows English) dan nilai 128-255 dari unicode sebagian besar sama, jadi jika itu codepage yang Anda gunakan sebagian besar karakter itu harus dipotong ke yang benar nilai-nilai. (Saya benar-benar berharap á dan õ bekerja, saya tahu kode kami di tempat kerja bergantung pada ini untuk é, yang akan segera saya perbaiki)
Mooing Duck
2
Ini sangat bagus. MSVS 2015 dan MSVS 2017 dan MINGW / g ++ dan dentang ++. Legit ++ 1.
Nikos
11

Alih-alih menyertakan lokal dan semua barang mewah itu, jika Anda tahu FACT string Anda dapat dikonversi, lakukan saja ini:

#include <iostream>
#include <string>

using namespace std;

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

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

Contoh langsung di sini

rubenvb
sumber
2
+1 karena ini adalah solusi sederhana yang berfungsi untuk beberapa skenario (untuk definisi longgar "berfungsi", saya dapat menambahkan).
gagak
2
Hampir sama dengan solusi namar0x0309, yang jauh lebih elegan IMHO. Tapi itu hanya aku.
onitake
Saya menambahkan kode Anda untuk benar-benar bekerja dengan modifikasi minimal ;-)
rubenvb
9
-1 Jika Anda memiliki wstring, kemungkinan Anda berurusan dengan karakter multibyte. Jika Anda tahu bahwa string itu sepele konversi, Anda tidak akan menangani wstring di tempat pertama. Kemungkinan besar, Anda berurusan dengan perpustakaan lain yang mengharapkan Anda untuk menangani wstring dengan benar. Memotong wchars hanya memohon bug yang sulit dilacak di kemudian hari. Anda juga harus menggunakan "hasil string (w.begin (), w.end ());" jika Anda akan melakukannya, untuk menghindari loop yang dapat memicu banyak realokasi.
Kian
7

Saya percaya bahwa cara resmi masih berlaku untuk semua codecvtaspek (Anda perlu semacam terjemahan sadar-lokal), seperti dalam

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

atau sesuatu seperti itu, saya tidak memiliki kode kerja di sekitar. Tapi saya tidak yakin berapa banyak orang saat ini menggunakan mesin itu dan berapa banyak yang hanya meminta pointer ke memori dan membiarkan ICU atau perpustakaan lain menangani detail berdarah.

Christopher Creutzig
sumber
7

Ada dua masalah dengan kode:

  1. Konversi dalam const std::string s( ws.begin(), ws.end() );tidak diperlukan untuk memetakan karakter lebar dengan benar ke rekan sempitnya. Kemungkinan besar, setiap karakter lebar hanya akan typecast ke char.
    Resolusi untuk masalah ini sudah diberikan dalam jawaban oleh kem dan melibatkannarrow fungsi dari sisi lokal ctype.

  2. Anda menulis keluaran untuk keduanya std::coutdan std::wcoutdalam program yang sama. Keduanya coutdan wcoutdikaitkan dengan aliran yang sama ( stdout) dan hasil menggunakan aliran yang sama baik sebagai aliran berorientasi byte (seperti couthalnya) dan aliran berorientasi lebar (seperti wcouthalnya) tidak didefinisikan.
    Pilihan terbaik adalah menghindari pencampuran output sempit dan lebar ke aliran (mendasar) yang sama. Untuk stdout/ cout/ wcout, Anda dapat mencoba mengalihkan orientasi stdoutketika beralih antara output lebar dan sempit (atau sebaliknya):

    #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
sumber
Ya, itu memperbaiki masalah dengan menggunakan cout dan wcout.
BЈовић
7

Pengkodean default aktif:

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

Kode ini memiliki dua bentuk untuk mengkonversi std :: string ke std :: wstring dan std :: wstring ke std :: string. Jika Anda meniadakan # jika didefinisikan WIN32, Anda mendapatkan hasil yang sama.

1. std :: string ke 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 ke 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. Pada windows Anda perlu mencetak unicode, menggunakan 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. Di program utama.

#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. Terakhir, Anda memerlukan dukungan yang kuat dan lengkap untuk karakter unicode di konsol. Saya merekomendasikan ConEmu dan ditetapkan sebagai terminal default pada Windows . Anda perlu menghubungkan Visual Studio ke ConEmu. Ingat bahwa file exe Visual Studio adalah devenv.exe

Diuji pada Visual Studio 2017 dengan VC ++; std = c ++ 17.

Hasil

Hasil1

Joma
sumber
6

Anda mungkin juga cukup menggunakan metode sempit ctype facet secara langsung:

#sertakan <clocale>
#sertakan <lokasi>
#termasuk <string>
#sertakan <vektor>

inline std :: string sempit (std :: wstring const & text)
{
    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 (dari, dari + len, '_', & buffer [0]);
    return std :: string (& buffer [0], & buffer [len]);
}
mensahkan
sumber
6

Pada saat menulis jawaban ini, pencarian google nomor satu untuk "convert string wstring" akan mendaratkan Anda di halaman ini. Jawaban saya menunjukkan bagaimana mengkonversi string ke wstring, meskipun ini BUKAN pertanyaan yang sebenarnya, dan saya mungkin harus menghapus jawaban ini, tetapi itu dianggap bentuk yang buruk. Anda mungkin ingin melompat ke jawaban StackOverflow ini , yang sekarang berperingkat lebih tinggi dari halaman ini.


Berikut adalah cara untuk menggabungkan konstanta string, wstring dan string campuran ke wstring. Gunakan kelas 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
sumber
13
Ini bukan konversi string ke string
poitroae
1
@Michael Bisakah Anda jelaskan? Bagaimana dengan ini tidak benar? Komentar Anda tidak membantu tanpa rincian lebih lanjut.
Nate
1
ini adalah string untuk meregangkan konversi. yaitu kebalikan dari pertanyaan.
Jeff McClintock
4

Selain hanya mengonversi jenis, Anda juga harus sadar tentang format aktual string.

Ketika mengkompilasi untuk Multi-byte Character set Visual Studio dan Win API mengasumsikan UTF8 (Sebenarnya windows encoding yang merupakan Windows-28591 ).
Saat mengkompilasi untuk Unicode Character set Visual studio dan Win API mengasumsikan UTF16.

Jadi, Anda harus mengonversi string dari format UTF16 ke UTF8 juga, dan tidak hanya mengonversi ke std :: string.
Ini akan menjadi perlu ketika bekerja dengan format multi-karakter seperti beberapa bahasa non-latin.

Idenya adalah untuk memutuskan yang std::wstring selalu mewakili UTF16 .
Dan std::string selalu mewakili UTF8 .

Ini tidak diberlakukan oleh kompiler, ini lebih merupakan kebijakan yang baik untuk dimiliki. Perhatikan awalan string yang saya gunakan untuk mendefinisikan UTF16 ( L ) dan UTF8 ( u8 ).

Untuk mengkonversi antara 2 jenis, Anda harus menggunakan: 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
sumber
3

Dalam kasus saya, saya harus menggunakan karakter multibyte (MBCS), dan saya ingin menggunakan std :: string dan std :: wstring. Dan tidak bisa menggunakan c ++ 11. Jadi saya menggunakan mbstowcs dan wcstombs.

Saya membuat fungsi yang sama dengan menggunakan baru, hapus [], tetapi lebih lambat dari ini.

Ini dapat membantu Cara: Mengkonversi Berbagai Jenis String

EDIT

Namun, dalam kasus konversi ke string wstring dan sumber tidak ada alfabet dan string multi byte, itu tidak berfungsi. Jadi saya mengubah wcstombs menjadi 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 untuk menggunakan 'MultiByteToWideChar' alih-alih '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
sumber
Bagaimana saya bisa menggunakan "wcstombs_s" dengan gcc 4.8? Karena saya melihat itu adalah fitur C ++ 11.
cristian
@ Kristen Anda dapat menggunakan versi "tidak aman" dari fungsi ini wcstombs().
Wazir
3

Solusi ini terinspirasi dari solusi dk123 , tetapi menggunakan aspek codecvt yang bergantung pada lokal. Hasilnya dalam string yang disandikan lokal bukannya UTF-8 (jika tidak ditetapkan sebagai lokal):

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

Saya sedang mencarinya, tetapi saya tidak dapat menemukannya. Akhirnya saya menemukan bahwa saya bisa mendapatkan aspek yang tepat dari std::localemenggunakan std::use_facet()fungsi dengan nama ketik yang tepat. Semoga ini membantu.

Kedok
sumber
Wazir, apa keuntungan (jika ada) mengkonversi dengan sisi tergantung lokal?
Marc.2377
Jika Anda bekerja dengan string dari sistem, dari input konsol misalnya.
Wazir
1

Jika ada orang lain yang tertarik: Saya membutuhkan kelas yang dapat digunakan secara bergantian di mana pun stringatau wstringdiharapkan. Kelas berikut convertible_string, berdasarkan solusi dk123 ini , dapat diinisialisasi dengan baik string, char const*, wstringatau wchar_t const*dan dapat ditugaskan oleh atau implisit dikonversi ke salah satu stringatau wstring(sehingga dapat diteruskan ke dalam sebuah fungsi yang mengambil baik).

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
sumber
1
Saya lebih suka menyimpan sebuah std::wstringdi kelas, daripada menyimpan std::stringdan melakukan konversi std::wstringketika diperlukan untuk mendapatkan std::wstring. Karena std::wstringagak lebih cepat daripada std::stringdan lebih kompatibel. Bahkan itu menghabiskan lebih banyak memori daripada 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); }
deep125
sumber
-1

Saya menggunakan di bawah ini untuk mengkonversi wstring ke string.

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
sumber
Anda sepertinya tidak memiliki header standar ( <string>) dan definisi untuk WideCharToMultiByte()- apakah ada beberapa pembungkus 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
sumber
3
tolong jelaskan apa yang ure lakukan di sana dalam jawaban Anda, kalau tidak itu akan dihapus
CodeFanatic
1
Di mana fungsi UTF8string berasal?
Jean-Christophe Blanchard