string
? wstring
?
std::string
adalah basic_string
templated pada a char
, dan std::wstring
pada a wchar_t
.
char
vs. wchar_t
char
seharusnya memiliki karakter, biasanya karakter 8-bit.
wchar_t
seharusnya memiliki karakter yang luas, dan kemudian, hal menjadi rumit:
Di Linux, a wchar_t
adalah 4 byte, sedangkan pada Windows, itu 2 byte.
Bagaimana dengan Unicode ?
Masalahnya adalah tidak satu char
pun wchar_t
secara langsung terkait dengan unicode.
Di Linux?
Mari kita mengambil OS Linux: Sistem Ubuntu saya sudah sadar unicode. Ketika saya bekerja dengan string char, itu secara asli dikodekan dalam UTF-8 (yaitu string Unicode karakter). Kode berikut:
#include <cstring>
#include <iostream>
int main(int argc, char* argv[])
{
const char text[] = "olé" ;
std::cout << "sizeof(char) : " << sizeof(char) << std::endl ;
std::cout << "text : " << text << std::endl ;
std::cout << "sizeof(text) : " << sizeof(text) << std::endl ;
std::cout << "strlen(text) : " << strlen(text) << std::endl ;
std::cout << "text(ordinals) :" ;
for(size_t i = 0, iMax = strlen(text); i < iMax; ++i)
{
std::cout << " " << static_cast<unsigned int>(
static_cast<unsigned char>(text[i])
);
}
std::cout << std::endl << std::endl ;
// - - -
const wchar_t wtext[] = L"olé" ;
std::cout << "sizeof(wchar_t) : " << sizeof(wchar_t) << std::endl ;
//std::cout << "wtext : " << wtext << std::endl ; <- error
std::cout << "wtext : UNABLE TO CONVERT NATIVELY." << std::endl ;
std::wcout << L"wtext : " << wtext << std::endl;
std::cout << "sizeof(wtext) : " << sizeof(wtext) << std::endl ;
std::cout << "wcslen(wtext) : " << wcslen(wtext) << std::endl ;
std::cout << "wtext(ordinals) :" ;
for(size_t i = 0, iMax = wcslen(wtext); i < iMax; ++i)
{
std::cout << " " << static_cast<unsigned int>(
static_cast<unsigned short>(wtext[i])
);
}
std::cout << std::endl << std::endl ;
return 0;
}
menampilkan teks berikut:
sizeof(char) : 1
text : olé
sizeof(text) : 5
strlen(text) : 4
text(ordinals) : 111 108 195 169
sizeof(wchar_t) : 4
wtext : UNABLE TO CONVERT NATIVELY.
wtext : ol�
sizeof(wtext) : 16
wcslen(wtext) : 3
wtext(ordinals) : 111 108 233
Anda akan melihat teks "olé" di char
benar-benar dibangun oleh empat karakter: 110, 108, 195 dan 169 (tidak termasuk nol di belakangnya). (Saya akan membiarkan Anda mempelajari wchar_t
kode sebagai latihan)
Jadi, ketika bekerja dengan char
Linux, Anda biasanya harus menggunakan Unicode tanpa menyadarinya. Dan seperti std::string
bekerja dengan char
, jadi std::string
sudah siap-unicode.
Perhatikan bahwa std::string
, seperti API string C, akan menganggap string "olé" memiliki 4 karakter, bukan tiga. Jadi Anda harus berhati-hati saat memotong / bermain dengan karakter unicode karena beberapa kombinasi karakter dilarang di UTF-8.
Di Windows?
Di Windows, ini sedikit berbeda. Win32 harus mendukung banyak aplikasi yang bekerja dengan char
dan pada berbagai charset / codepages yang diproduksi di seluruh dunia, sebelum munculnya Unicode.
Jadi solusi mereka sangat menarik: Jika sebuah aplikasi bekerja char
, maka string char dikodekan / dicetak / ditampilkan pada label GUI menggunakan charset / codepage lokal pada mesin. Misalnya, "olé" akan menjadi "olé" di Windows yang dilokalisasikan di Prancis, tetapi akan menjadi sesuatu yang berbeda pada Windows yang dilokalisasi dengan cyrillic ("olй" jika Anda menggunakan Windows-1251 ). Dengan demikian, "aplikasi historis" biasanya akan tetap bekerja dengan cara lama yang sama.
Untuk aplikasi berbasis Unicode, Windows menggunakan wchar_t
, yang lebar 2-byte, dan dikodekan dalam UTF-16 , yang Unicode dikodekan pada karakter 2-byte (atau paling tidak, UCS-2 yang paling kompatibel, yang hampir merupakan hal yang sama IIRC).
Aplikasi yang menggunakan char
dikatakan "multibyte" (karena setiap mesin terbang terdiri dari satu atau lebih char
s), sedangkan aplikasi yang menggunakan wchar_t
dikatakan "widechar" (karena masing-masing mesin terbang terdiri dari satu atau dua wchar_t
. Lihat MultiByteToWideChar dan WideCharToMultiByte Win32 API konversi untuk info lebih lanjut.
Jadi, jika Anda bekerja di Windows, Anda sangat ingin menggunakan wchar_t
(kecuali jika Anda menggunakan kerangka kerja yang menyembunyikan itu, seperti GTK + atau QT ...). Faktanya adalah bahwa di balik layar, Windows bekerja dengan wchar_t
string, sehingga bahkan aplikasi historis akan memiliki char
string mereka dikonversi wchar_t
ketika menggunakan API seperti SetWindowText()
(fungsi API tingkat rendah untuk mengatur label pada Win32 GUI).
Masalah memori?
UTF-32 adalah 4 byte per karakter, jadi tidak ada banyak yang harus ditambahkan, jika saja teks UTF-8 dan teks UTF-16 akan selalu menggunakan lebih sedikit atau jumlah memori yang sama dari teks UTF-32 (dan biasanya kurang ).
Jika ada masalah memori, maka Anda harus tahu daripada kebanyakan bahasa barat, teks UTF-8 akan menggunakan memori lebih sedikit daripada UTF-16 yang sama.
Namun, untuk bahasa lain (Cina, Jepang, dll.), Memori yang digunakan akan sama, atau sedikit lebih besar untuk UTF-8 daripada untuk UTF-16.
Secara keseluruhan, UTF-16 sebagian besar akan menggunakan 2 dan kadang-kadang 4 byte per karakter (kecuali jika Anda berurusan dengan beberapa jenis mesin terbang bahasa esoterik (Klingon? Peri?), Sedangkan UTF-8 akan menghabiskan 1 hingga 4 byte.
Lihat http://en.wikipedia.org/wiki/UTF-8#Compared_to_UTF-16 untuk info lebih lanjut.
Kesimpulan
Kapan saya harus menggunakan std :: wstring over std :: string?
Di Linux? Hampir tidak pernah (§).
Di Windows? Hampir selalu (§).
Pada kode lintas platform? Tergantung pada perangkat Anda ...
(§): kecuali Anda menggunakan toolkit / kerangka kerja yang mengatakan sebaliknya
Bisakah std::string
memegang semua set karakter ASCII termasuk karakter khusus?
Perhatikan: A std::string
cocok untuk memegang buffer 'biner', di mana a std::wstring
tidak!
Di Linux? Iya.
Di Windows? Hanya karakter khusus yang tersedia untuk lokal saat ini dari pengguna Windows.
Sunting (Setelah komentar dari Johann Gerell ):
a std::string
akan cukup untuk menangani semua char
string berbasis (masing char
- masing berupa angka dari 0 hingga 255). Tapi:
- ASCII seharusnya berubah dari 0 menjadi 127. Semakin tinggi
char
BUKAN ASCII.
- a
char
dari 0 hingga 127 akan disimpan dengan benar
- a
char
dari 128 hingga 255 akan memiliki signifikasi tergantung pada pengkodean Anda (unicode, non-unicode, dll.), tetapi itu akan dapat menampung semua mesin terbang Unicode selama kode tersebut dikodekan dalam UTF-8.
Apakah std::wstring
didukung oleh hampir semua kompiler C ++ yang populer?
Sebagian besar, dengan pengecualian kompiler berbasis GCC yang porting ke Windows.
Ini bekerja pada g ++ 4.3.2 saya (di Linux), dan saya menggunakan Unicode API di Win32 sejak Visual C ++ 6.
Apa sebenarnya karakter yang lebar?
Pada C / C ++, ini adalah tipe karakter yang ditulis wchar_t
yang lebih besar dari char
tipe karakter sederhana . Seharusnya digunakan untuk memasukkan karakter di dalam yang indeksnya (seperti mesin terbang Unicode) lebih besar dari 255 (atau 127, tergantung ...).