string? wstring?
std::stringlà một basic_stringtemplated trên a char, và std::wstringtrên a wchar_t.
char so với wchar_t
charđược cho là giữ một ký tự, thường là ký tự 8 bit.
wchar_tđược cho là có một ký tự rộng, và sau đó, mọi thứ trở nên khó khăn:
Trên Linux, a wchar_tlà 4 byte, trong khi trên Windows, đó là 2 byte.
Thế còn Unicode thì sao?
Vấn đề là không phải charvà cũng không wchar_tđược gắn trực tiếp vào unicode.
Trên Linux?
Hãy dùng HĐH Linux: Hệ thống Ubuntu của tôi đã nhận biết được unicode. Khi tôi làm việc với một chuỗi char, nó được mã hóa nguyên bản trong UTF-8 (tức là chuỗi ký tự Unicode). Các mã sau đây:
#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;
}
xuất văn bản sau:
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
Bạn sẽ thấy văn bản "olé" charthực sự được xây dựng bởi bốn ký tự: 110, 108, 195 và 169 (không tính số 0 ở cuối). (Tôi sẽ cho bạn học wchar_tmã như một bài tập)
Vì vậy, khi làm việc với charLinux, bạn thường nên sử dụng Unicode mà không hề biết. Và như đã std::stringlàm việc với char, vì vậy std::stringđã sẵn sàng unicode.
Lưu ý rằng std::string, giống như API chuỗi C, sẽ xem xét chuỗi "olé" có 4 ký tự, không phải ba ký tự. Vì vậy, bạn nên thận trọng khi cắt / chơi với ký tự unicode vì một số tổ hợp ký tự bị cấm trong UTF-8.
Trên Windows?
Trên Windows, điều này hơi khác một chút. Win32 đã phải hỗ trợ rất nhiều ứng dụng hoạt động cùng charvà trên các bộ mã / bảng mã khác nhau được sản xuất trên toàn thế giới, trước khi Unicode ra đời.
Vì vậy, giải pháp của họ là một điều thú vị: Nếu một ứng dụng hoạt động với char, thì chuỗi char được mã hóa / in / hiển thị trên nhãn GUI bằng cách sử dụng bộ ký tự / bảng mã cục bộ trên máy. Ví dụ: "olé" sẽ là "olé" trong Windows được bản địa hóa bằng tiếng Pháp, nhưng sẽ là một cái gì đó khác biệt trên Windows được bản địa hóa bằng cyrillic ("olй" nếu bạn sử dụng Windows-1251 ). Do đó, "ứng dụng lịch sử" thường sẽ vẫn hoạt động theo cùng một cách cũ.
Đối với các ứng dụng dựa trên Unicode, Windows sử dụng wchar_t, rộng 2 byte và được mã hóa theo UTF-16 , được mã hóa Unicode trên các ký tự 2 byte (hoặc ít nhất là UCS-2 tương thích, hầu như là điều tương tự IIRC).
Các ứng dụng sử dụng charđược gọi là "multibyte" (vì mỗi glyph bao gồm một hoặc nhiều chars), trong khi các ứng dụng sử dụng wchar_tđược gọi là "widechar" (vì mỗi glyph bao gồm một hoặc hai wchar_t. Xem API chuyển đổi MultiByteToWideChar và WideCharToMultiByte Win32 để biết thêm.
Do đó, nếu bạn làm việc trên Windows, bạn rất muốn sử dụng wchar_t(trừ khi bạn sử dụng một khung ẩn, như GTK + hoặc QT ...). Thực tế là đằng sau hậu trường, Windows hoạt động với các wchar_tchuỗi, vì vậy ngay cả các ứng dụng lịch sử cũng sẽ có các charchuỗi được chuyển đổi wchar_tkhi sử dụng API như SetWindowText()(hàm API cấp thấp để đặt nhãn trên GUI Win32).
Vấn đề bộ nhớ?
UTF-32 là 4 byte cho mỗi ký tự, vì vậy không có gì nhiều để thêm, nếu chỉ có văn bản UTF-8 và văn bản UTF-16 sẽ luôn sử dụng ít hơn hoặc cùng một lượng bộ nhớ so với văn bản UTF-32 (và thường ít hơn ).
Nếu có vấn đề về bộ nhớ, thì bạn nên biết hơn so với hầu hết các ngôn ngữ phương Tây, văn bản UTF-8 sẽ sử dụng ít bộ nhớ hơn so với cùng một ngôn ngữ UTF-16.
Tuy nhiên, đối với các ngôn ngữ khác (tiếng Trung, tiếng Nhật, v.v.), bộ nhớ được sử dụng sẽ giống nhau hoặc lớn hơn một chút đối với UTF-8 so với UTF-16.
Nói chung, UTF-16 chủ yếu sẽ sử dụng 2 và đôi khi 4 byte cho mỗi ký tự (trừ khi bạn đang xử lý một loại glyphs ngôn ngữ bí truyền (Klingon? Elvish?), Trong khi UTF-8 sẽ tiêu tốn từ 1 đến 4 byte.
Xem http://en.wikipedia.org/wiki/UTF-8#Compared_to_UTF-16 để biết thêm thông tin.
Phần kết luận
Khi nào tôi nên sử dụng std :: wopes over std :: string?
Trên Linux? Hầu như không bao giờ (§).
Trên Windows? Gần như luôn luôn (§).
Trên mã đa nền tảng? Phụ thuộc vào bộ công cụ của bạn ...
(§): trừ khi bạn sử dụng bộ công cụ / khung nói khác
Có thể std::stringchứa tất cả các bộ ký tự ASCII bao gồm các ký tự đặc biệt không?
Lưu ý: A std::stringphù hợp để giữ bộ đệm 'nhị phân', trong đó a std::wstringkhông!
Trên Linux? Đúng.
Trên Windows? Chỉ các ký tự đặc biệt có sẵn cho ngôn ngữ hiện tại của người dùng Windows.
Chỉnh sửa (Sau khi nhận xét từ Johann Gerell ):
a std::stringsẽ đủ để xử lý tất cả các charchuỗi dựa trên (mỗi chuỗi charlà một số từ 0 đến 255). Nhưng:
- ASCII được cho là đi từ 0 đến 127. Cao hơn
charKHÔNG phải là ASCII.
- a
chartừ 0 đến 127 sẽ được giữ đúng
- a
chartừ 128 đến 255 sẽ có một dấu hiệu tùy thuộc vào mã hóa của bạn (unicode, không unicode, v.v.), nhưng nó sẽ có thể giữ tất cả các glyph Unicode miễn là chúng được mã hóa trong UTF-8.
Được std::wstringhỗ trợ bởi hầu hết tất cả các trình biên dịch C ++ phổ biến?
Hầu hết, ngoại trừ các trình biên dịch dựa trên GCC được chuyển sang Windows.
Nó hoạt động trên g ++ 4.3.2 của tôi (trong Linux) và tôi đã sử dụng API Unicode trên Win32 kể từ Visual C ++ 6.
Chính xác một nhân vật rộng là gì?
Trên C / C ++, đây là loại ký tự được viết wchar_tlớn hơn charloại ký tự đơn giản . Nó được cho là được sử dụng để đặt bên trong các ký tự có chỉ số (như glyphs Unicode) lớn hơn 255 (hoặc 127, tùy thuộc ...).