Saya tidak berpikir stringsmenerima> karakter 8-bit. Apakah sudah dikodekan dalam UTF-8?
kennytm
3
Apa pengkodean sistem Anda yang akan membuat "おはよう"string yang dikodekan sistem?
sbi
Saya percaya MSVC akan menerimanya dan membuatnya menjadi pengkodean multibyte, mungkin UTF-8.
Potatoswatter
1
@Potatoswatter: MSVC tidak menggunakan UTF-8 secara default untuk APA SAJA. Jika Anda memasukkan karakter tersebut, ia meminta pengkodean untuk mengkonversi file, dan default ke codepage 1252.
Mooing Duck
2
@ Samir: lebih penting apa pengkodean file ? Bisakah Anda memindahkan string itu ke awal file dan menunjukkan hexdump dari bagian itu? Kita mungkin bisa mengidentifikasinya dari itu.
Mooing Duck
Jawaban:
239
Mengasumsikan bahwa string input dalam contoh Anda (お は よ う) adalah UTF-8 yang dikodekan (yang tidak terlihat seperti itu, tetapi mari kita asumsikan itu demi penjelasan ini :-)) representasi dari string Unicode yang Anda minati, maka masalah Anda dapat diselesaikan dengan perpustakaan standar (C ++ 11 dan yang lebih baru) saja.
Seperti yang ditunjukkan dalam komentar dan dijelaskan di https://stackoverflow.com/a/17106065/6345 ada beberapa kasus ketika menggunakan perpustakaan standar untuk mengkonversi antara UTF-8 dan UTF-16 mungkin memberikan perbedaan yang tidak terduga dalam hasil pada platform yang berbeda . Untuk konversi yang lebih baik, pertimbangkan std::codecvt_utf8seperti yang dijelaskan pada http://en.cppreference.com/w/cpp/locale/codecvt_utf8
Ini hanya berfungsi jika semua karakter adalah byte tunggal, yaitu ASCII atau ISO-8859-1 . Multi-byte apa pun akan gagal total, termasuk UTF-8. Pertanyaannya jelas berisi karakter multi-byte.
Mark Ransom
28
Jawaban ini jelas tidak cukup dan tidak melakukan apa-apa selain menyalin karakter sempit seperti ke karakter lebar. Lihat jawaban lain, terutama yang oleh Johann Gerell, untuk cara beralih dari multi-byte atau utf8 encoded string ke utf16 wstring.
DLRdave
10
jawaban ini berbahaya dan mungkin akan rusak pada sistem non-ascii. yaitu nama file arab akan hancur oleh hack ini.
Stephen
9
Jawaban ini berguna jika Anda mengabaikan nuansa tubuh pertanyaan dan fokus pada judul pertanyaan, yang membawa saya ke sini dari Google. Seperti, judul pertanyaan itu sangat menyesatkan dan harus diubah untuk mencerminkan pertanyaan sebenarnya yang diajukan
Anne Quinn
3
Ini hanya berfungsi untuk karakter ASCII 7-bit. Untuk latin1, ini hanya berfungsi jika char dikonfigurasikan sebagai unsigned. Jika tipe char ditandatangani (yang biasanya terjadi), karakter> 127 akan memberikan hasil yang salah.
huyc
32
Pertanyaan Anda kurang spesifik. Sebenarnya, contoh itu adalah kesalahan sintaksis. Namun, std::mbstowcsmungkin itu yang Anda cari.
Ini adalah fungsi C-library dan beroperasi pada buffer, tapi di sini adalah idiom yang mudah digunakan, milik TBohne (sebelumnya 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: Anda harus memastikan pengkodean runtime sama dengan pengkodean waktu kompilasi. Anda mungkin perlu setlocaleatau menyesuaikan flag compiler. Saya tidak tahu karena saya tidak menggunakan Windows, tetapi inilah mengapa ini bukan fitur yang umum. Pertimbangkan jawaban yang lain jika memungkinkan.
@WaffleSouffle Itu sudah ketinggalan zaman. Implementasi yang berdekatan telah diperlukan sejak 2011 dan implementasi berhenti trik seperti itu jauh sebelum itu.
Potatoswatter
1
dan beberapa lingkungan seperti mingw masih belum memiliki header codecvt sehingga beberapa solusi 'lebih baik' sebelumnya tidak berfungsi yang berarti masalah ini masih belum memiliki solusi yang baik di mingw bahkan pada Desember 2014
Brian Jack
18
Hanya Windows API, sebelum implementasi C ++ 11, jika seseorang membutuhkannya:
Anda bisa mengoptimalkannya. Tidak perlu melakukan duplikat string dengan menggunakan a vector. Cukup cadangan karakter dalam string dengan melakukan wstring strW(charsNeeded + 1);dan kemudian menggunakannya sebagai penyangga untuk konversi: &strW[0]. Terakhir memastikan nol terakhir ada setelah konversi dengan melakukanstrW[charsNeeded] = 0;
c00000fd
1
@ c00000fd, sejauh yang saya tahu, std :: basic_string buffer internal harus kontinu hanya karena standar C ++ 11. Kode saya adalah pra C ++ 11, sebagaimana tercantum di bagian atas posting. Karenanya, kode & strW [0] tidak sesuai standar dan mungkin mogok secara sah saat runtime.
Alex Che
13
Jika Anda menggunakan Windows / Visual Studio dan perlu mengonversi string ke wstring Anda bisa menggunakan:
#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());
Prosedur yang sama untuk mengonversi wstring ke string (kadang-kadang Anda harus menentukan codepage ):
#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);}
Kadang-kadang Anda harus menonaktifkan peringatan keamanan # 4995 ', saya tidak tahu solusi lain (bagi saya itu terjadi ketika saya dikompilasi untuk Windows XP di VS2012).
Maaf saya bukan penutur asli bahasa Inggris. Harap edit sesuai keinginan Anda.
lmiguelmh
Ada apa dengan downvoter? Apa yang salah dengan jawabannya?
lmiguelmh
Mungkin fakta bahwa itu mempromosikan kode non-portabel.
Pavel Minaev
Ya, itu sebabnya saya menyatakan bahwa ini hanya berfungsi di Windows / Visual Studio. Tapi setidaknya solusi ini benar, dan bukan yang ini:char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
lmiguelmh
Catatan tambahan: CA2W berada di bawah namespace ATL. (ATL :: CA2W)
Val
12
Inilah cara menggabungkan string, wstringdan menggabungkan konstanta string ke wstring. Gunakan wstringstreamkelas.
Ini TIDAK berfungsi untuk pengkodean karakter multi-byte. Ini hanya cara bodoh membuang keamanan tipe dan memperluas karakter 7 bit dari std :: string ke dalam 7 bit yang lebih rendah dari setiap karakter std: wstring. Ini hanya berguna jika Anda memiliki string ASCII 7-bit dan Anda perlu memanggil API yang membutuhkan string luas.
Jawabannya sepertinya menarik. Bisakah Anda jelaskan sedikit: apakah ini akan berfungsi untuk pengkodean multi-byte, dan mengapa / bagaimana?
wh1t3cat1k
skema pengkodean adalah ortogonal ke kelas penyimpanan. stringmenyimpan 1 byte karakter dan wstringmenyimpan 2 byte karakter. sesuatu seperti utf8 menyimpan karakter mulitbyte sebagai rangkaian nilai 1 byte, yaitu dalam a string. kelas string tidak membantu pengodean. Saya bukan ahli pengkodean kelas di c ++.
Mark Lakata
2
Adakah alasan mengapa jawaban ini bukan jawaban terbaik, mengingat betapa singkat dan sederhananya itu? Adakah kasus yang tidak dicakup?
Ryuu
@ Markakata, saya membaca jawaban Anda untuk komentar pertama tetapi saya masih tidak yakin. Apakah ini akan berfungsi untuk karakter multi-byte? Dengan kata lain, apakah itu tidak rentan terhadap jebakan yang sama dengan jawaban ini ?
Marc.2377
@ Marc.2377 Ini TIDAK berfungsi untuk pengkodean karakter multi-byte. Ini hanya cara bodoh membuang jenis keselamatan dan memperluas karakter 7 bit dari std::stringke 7 bit yang lebih rendah dari masing-masing karakter std:wstring. Ini hanya berguna jika Anda memiliki string ASCII 7-bit dan Anda perlu memanggil API yang membutuhkan string luas. Lihatlah stackoverflow.com/a/8969776/3258851 jika Anda membutuhkan sesuatu yang lebih canggih.
Karena ini hanya berfungsi jika penyandiannya adalah Windows-1252, yang bahkan tidak dapat menahan huruf dalam pertanyaan.
Mooing Duck
3
ini adalah cara paling rawan kesalahan dalam melakukannya, ketika Anda tahu Anda berurusan dengan ASCII. Yang merupakan usecase yang menonjol saat porting aplikasi ke api yang lebih baru.
Sid Sarasvati
Ini bukan jalannya. Jika Anda menggunakan Visual Studio, Anda harus menggunakan atlconv.h. Periksa jawaban lainnya.
Varian ini adalah favorit saya di kehidupan nyata. Itu mengkonversi input, jika itu valid UTF-8, untuk masing-masing wstring. Jika input rusak, wstringitu dibangun dari byte tunggal. Ini sangat membantu jika Anda tidak benar-benar yakin tentang kualitas data input Anda.
Apa dengan semua jawaban ini yang mengalokasikan memori dinamis dengan cara yang tidak aman, dan kemudian menyalin data dari buffer ke string? Mengapa tidak ada yang menyingkirkan tengkulak tidak aman?
Mooing Duck
hahakubile, bisakah Anda membantu dengan sesuatu yang serupa untuk ws2s?
cristian
1
Berdasarkan pengujian saya sendiri (Pada windows 8, vs2010) mbstowcs sebenarnya dapat merusak string asli, ia hanya bekerja dengan halaman kode ANSI. Jika MultiByteToWideChar / WideCharToMultiByte juga dapat menyebabkan korupsi string - tetapi mereka cenderung mengganti karakter yang tidak mereka kenal dengan '?' tanda tanya, tetapi mbstowc cenderung berhenti ketika bertemu dengan karakter yang tidak dikenal dan memotong string pada saat itu. (Saya telah menguji karakter Vietnam di windows Finlandia).
Jadi lebih suka Multi * -windows fungsi api daripada fungsi ansi C analog.
Juga apa yang saya perhatikan cara terpendek untuk menyandikan string dari satu codepage ke yang lain tidak menggunakan MultiByteToWideChar / WideCharToMultiByte panggilan fungsi api tetapi analog ATL makro mereka: W2A / A2W.
Jadi fungsi analog seperti yang disebutkan di atas akan terdengar seperti:
Tetapi harap perhatikan bahwa makro itu sangat banyak menggunakan stack - jangan gunakan untuk loop atau loop rekursif untuk fungsi yang sama - setelah menggunakan makro W2A atau A2W - lebih baik untuk mengembalikan ASAP, jadi stack akan dibebaskan dari konversi sementara.
Str2Wstr ini memiliki masalah dengan 0 terminasi. Tidak mungkin untuk menyatukan wstrings yang dihasilkan lagi melalui "+" (seperti di wstring s3 = s1 + s2). Saya akan mengirim jawaban segera menyelesaikan masalah ini. Harus melakukan beberapa pengujian untuk kebocoran memori terlebih dahulu.
Itu juga tidak akan berhasil. Anda harus mengonversi karakter non-BMP ke urutan pelarian C.
Dave Van den Eynde
3
@ Dave: ini berfungsi jika kompiler Anda mendukung unicode dalam file sumber, dan semua yang dalam dekade terakhir melakukannya (visual studio, gcc, ...)
Thomas Bonini
Hai, terlepas dari pengkodean sistem default (saya mungkin memiliki bahasa Arab sebagai pengkodean sistem default saya misalnya), apa yang seharusnya pengkodean file kode sumber untuk L "お は よ う" berfungsi? haruskah dalam UTF-16, atau bisakah saya memiliki UTF-8 tanpa BOM untuk pengkodean file .cpp?
Afriza N. Arief
2
@afriza: tidak masalah asalkan kompilasi Anda mendukungnya
Thomas Bonini
2
Itu bukan kesalahan; karakter diperluas dalam string "sempit" didefinisikan untuk memetakan ke urutan multibyte. Kompiler harus mendukungnya selama OS melakukannya, yang paling tidak bisa Anda tanyakan.
Potatoswatter
-2
gunakan kode ini untuk mengonversi string Anda menjadi wstring
Perhatikan bahwa pertanyaan tidak menyebutkan Windows dan jawaban ini hanya untuk Windows.
Johann Gerell
CP_ACPtentu saja argumen yang salah. Tiba-tiba, keadaan lingkungan thread yang mengeksekusi memiliki efek pada perilaku kode. Tidak disarankan. Tentukan penyandian karakter tetap dalam konversi Anda. (Dan pertimbangkan menangani kesalahan.)
strings
menerima> karakter 8-bit. Apakah sudah dikodekan dalam UTF-8?"おはよう"
string yang dikodekan sistem?Jawaban:
Mengasumsikan bahwa string input dalam contoh Anda (お は よ う) adalah UTF-8 yang dikodekan (yang tidak terlihat seperti itu, tetapi mari kita asumsikan itu demi penjelasan ini :-)) representasi dari string Unicode yang Anda minati, maka masalah Anda dapat diselesaikan dengan perpustakaan standar (C ++ 11 dan yang lebih baru) saja.
Versi TL; DR:
Contoh kompilasi dan runnable online yang lebih panjang:
(Mereka semua menunjukkan contoh yang sama. Hanya ada banyak untuk redundansi ...)
Catatan (lama) :
Seperti yang ditunjukkan dalam komentar dan dijelaskan di https://stackoverflow.com/a/17106065/6345 ada beberapa kasus ketika menggunakan perpustakaan standar untuk mengkonversi antara UTF-8 dan UTF-16 mungkin memberikan perbedaan yang tidak terduga dalam hasil pada platform yang berbeda . Untuk konversi yang lebih baik, pertimbangkan
std::codecvt_utf8
seperti yang dijelaskan pada http://en.cppreference.com/w/cpp/locale/codecvt_utf8Catatan (baru) :
Karena
codecvt
tajuk sudah usang dalam C ++ 17, beberapa kekhawatiran tentang solusi yang disajikan dalam jawaban ini dimunculkan. Namun, komite standar C ++ menambahkan pernyataan penting di http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html mengatakanJadi di masa mendatang,
codecvt
solusi dalam jawaban ini aman dan portabel.sumber
std::codecvt_utf8
untuk pemula<codecvt>
sudah usang sejak C ++ 17.sumber
Pertanyaan Anda kurang spesifik. Sebenarnya, contoh itu adalah kesalahan sintaksis. Namun,
std::mbstowcs
mungkin itu yang Anda cari.Ini adalah fungsi C-library dan beroperasi pada buffer, tapi di sini adalah idiom yang mudah digunakan, milik TBohne (sebelumnya Mooing Duck):
sumber
setlocale
atau menyesuaikan flag compiler. Saya tidak tahu karena saya tidak menggunakan Windows, tetapi inilah mengapa ini bukan fitur yang umum. Pertimbangkan jawaban yang lain jika memungkinkan.std::string ws(s.size()); ws.resize(mbstowcs(&ws[0], s.c_str(), s.size());
RAII FTWHanya Windows API, sebelum implementasi C ++ 11, jika seseorang membutuhkannya:
sumber
vector
. Cukup cadangan karakter dalam string dengan melakukanwstring strW(charsNeeded + 1);
dan kemudian menggunakannya sebagai penyangga untuk konversi:&strW[0]
. Terakhir memastikan nol terakhir ada setelah konversi dengan melakukanstrW[charsNeeded] = 0;
Jika Anda menggunakan Windows / Visual Studio dan perlu mengonversi string ke wstring Anda bisa menggunakan:
Prosedur yang sama untuk mengonversi wstring ke string (kadang-kadang Anda harus menentukan codepage ):
Anda dapat menentukan codepage dan bahkan UTF8 (itu cukup bagus ketika bekerja dengan JNI / Java ). Cara standar untuk mengubah string std :: wstring ke utf8 std :: ditunjukkan dalam jawaban ini .
Jika Anda ingin tahu lebih banyak tentang codepages ada artikel menarik tentang Joel tentang Perangkat Lunak: Minimum Yang Mutlak Setiap Pengembang Perangkat Lunak Sepenuhnya, Pasti Harus Tahu Tentang Unicode dan Set Karakter .
Makro CA2W (Konversi Ansi ke Lebar = unicode) ini adalah bagian dari Makro Konversi String ATL dan MFC , termasuk sampel.
Kadang-kadang Anda harus menonaktifkan peringatan keamanan # 4995 ', saya tidak tahu solusi lain (bagi saya itu terjadi ketika saya dikompilasi untuk Windows XP di VS2012).
Sunting: Yah, menurut artikel ini artikel oleh Joel tampaknya: "sambil menghibur, itu cukup ringan pada detail teknis yang sebenarnya". Artikel: Apa Yang Harus Semua Programmer Sepenuhnya Ingin Tahu Tentang Pengkodean dan Set Karakter Untuk Bekerja dengan Teks .
sumber
char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
Inilah cara menggabungkan
string
,wstring
dan menggabungkan konstanta string kewstring
. Gunakanwstringstream
kelas.Ini TIDAK berfungsi untuk pengkodean karakter multi-byte. Ini hanya cara bodoh membuang keamanan tipe dan memperluas karakter 7 bit dari std :: string ke dalam 7 bit yang lebih rendah dari setiap karakter std: wstring. Ini hanya berguna jika Anda memiliki string ASCII 7-bit dan Anda perlu memanggil API yang membutuhkan string luas.
sumber
string
menyimpan 1 byte karakter danwstring
menyimpan 2 byte karakter. sesuatu seperti utf8 menyimpan karakter mulitbyte sebagai rangkaian nilai 1 byte, yaitu dalam astring
. kelas string tidak membantu pengodean. Saya bukan ahli pengkodean kelas di c ++.std::string
ke 7 bit yang lebih rendah dari masing-masing karakterstd:wstring
. Ini hanya berguna jika Anda memiliki string ASCII 7-bit dan Anda perlu memanggil API yang membutuhkan string luas. Lihatlah stackoverflow.com/a/8969776/3258851 jika Anda membutuhkan sesuatu yang lebih canggih.Dari
char*
kewstring
:Dari
string
kewstring
:Perhatikan ini hanya berfungsi dengan baik jika string yang dikonversi hanya berisi karakter ASCII.
sumber
atlconv.h
. Periksa jawaban lainnya.menggunakan Boost.Locale:
sumber
Varian ini adalah favorit saya di kehidupan nyata. Itu mengkonversi input, jika itu valid UTF-8, untuk masing-masing
wstring
. Jika input rusak,wstring
itu dibangun dari byte tunggal. Ini sangat membantu jika Anda tidak benar-benar yakin tentang kualitas data input Anda.sumber
Jika Anda memiliki QT dan jika Anda malas menerapkan fungsi dan hal-hal yang dapat Anda gunakan
std :: string str; QString (str) .toStdWString ()
sumber
QString
, karenaQString
konstruktor tidak dapat menerima string karena suatu alasan.Metode s2ws bekerja dengan baik. Semoga bisa membantu.
sumber
Berdasarkan pengujian saya sendiri (Pada windows 8, vs2010) mbstowcs sebenarnya dapat merusak string asli, ia hanya bekerja dengan halaman kode ANSI. Jika MultiByteToWideChar / WideCharToMultiByte juga dapat menyebabkan korupsi string - tetapi mereka cenderung mengganti karakter yang tidak mereka kenal dengan '?' tanda tanya, tetapi mbstowc cenderung berhenti ketika bertemu dengan karakter yang tidak dikenal dan memotong string pada saat itu. (Saya telah menguji karakter Vietnam di windows Finlandia).
Jadi lebih suka Multi * -windows fungsi api daripada fungsi ansi C analog.
Juga apa yang saya perhatikan cara terpendek untuk menyandikan string dari satu codepage ke yang lain tidak menggunakan MultiByteToWideChar / WideCharToMultiByte panggilan fungsi api tetapi analog ATL makro mereka: W2A / A2W.
Jadi fungsi analog seperti yang disebutkan di atas akan terdengar seperti:
_acp dideklarasikan dalam makro USES_CONVERSION.
Atau juga fungsi yang sering saya lewatkan ketika melakukan konversi data lama ke yang baru:
Tetapi harap perhatikan bahwa makro itu sangat banyak menggunakan stack - jangan gunakan untuk loop atau loop rekursif untuk fungsi yang sama - setelah menggunakan makro W2A atau A2W - lebih baik untuk mengembalikan ASAP, jadi stack akan dibebaskan dari konversi sementara.
sumber
String to wstring
wstring ke String
sumber
string s = "おはよう";
adalah kesalahan.Anda harus menggunakan wstring secara langsung:
sumber
gunakan kode ini untuk mengonversi string Anda menjadi wstring
sumber
CP_ACP
tentu saja argumen yang salah. Tiba-tiba, keadaan lingkungan thread yang mengeksekusi memiliki efek pada perilaku kode. Tidak disarankan. Tentukan penyandian karakter tetap dalam konversi Anda. (Dan pertimbangkan menangani kesalahan.)