Tôi đã đọc một số bài viết về Unicode và nhận ra tôi vẫn còn nhầm lẫn những gì chính xác làm về nó.C++ string literal vẫn còn khó hiểu
Là một lập trình viên C++ trên nền tảng Windows, các môn học được trao cho tôi hầu như giống với bất kỳ giáo viên nào: luôn sử dụng bộ ký tự Unicode; templatize nó hoặc sử dụng TCHAR nếu có thể; thích wchar_t, std :: wstring trên char, std :: string.
#include <tchar.h>
#include <string>
typedef std::basic_string<TCHAR> tstring;
// ...
static const char* const s_hello = "핼로"; // bad
static const wchar_t* const s_wchar_hello = L"핼로" // better
static LPCTSTR s_tchar_hello = TEXT("핼로") // even better
static const tstring s_tstring_hello(TEXT("핼로")); // best
Bằng cách nào đó tôi đã sai lầm và tôi tự tin rằng nếu tôi nói "cái gì đó", có nghĩa là định dạng ASCII và nếu tôi nói L "cái gì đó" là Unicode. Sau đó, tôi đọc điều này:
Loại wchar_t là một loại riêng biệt có giá trị có thể đại diện cho các mã riêng biệt được chỉ định trong các ngôn ngữ được hỗ trợ (22.3.1). Loại wchar_t phải có cùng kích thước, ký kết và yêu cầu căn chỉnh (3.11) là một trong các kiểu tích phân khác, được gọi là kiểu cơ bản của nó. Các kiểu char16_t và char32_t biểu thị các kiểu riêng biệt với cùng kích cỡ, ký kết và căn chỉnh là uint_least16_t và uint_least32_t, tương ứng, được gọi là các kiểu cơ bản.
Vậy thì sao? Nếu ngôn ngữ của tôi nói bắt đầu từ mã 949, phần mở rộng của wchar_t là từ 949 + 2^(sizeof (wchar_t) * 8)? Và cách nó phát ra âm thanh như 'Tôi không quan tâm nếu việc bạn thực hiện C++ sử dụng mã hóa UTF hay cái gì'.
Ít nhất, tôi có thể hiểu rằng mọi thứ phụ thuộc vào ngôn ngữ mà ứng dụng đang bật. Vì vậy, tôi đã thử nghiệm:
#define TEST_OSTREAM_PRINT(x) \
std::cout << "----" << std::endl; \
std::cout << "cout : " << x << std::endl; \
std::wcout << "wcout : " << L##x << std::endl;
int main()
{
std::ostream& os = std::cout;
std::cout << " * Info : " << std::endl
<< " sizeof(char) : " << sizeof(char) << std::endl
<< " sizeof(wchar_t) : " << sizeof(wchar_t) << std::endl
<< " littel endian? : " << IsLittelEndian() << std::endl;
std::cout << " - LC_ALL: " << setlocale(LC_ALL, NULL) << std::endl;
std::cout << " - LC_CTYPE: " << setlocale(LC_CTYPE, NULL) << std::endl;
TEST_OSTREAM_PRINT("핼로");
TEST_OSTREAM_PRINT("おはよう。");
TEST_OSTREAM_PRINT("你好");
TEST_OSTREAM_PRINT("resume");
TEST_OSTREAM_PRINT("résumé");
return 0;
}
Sau đó, đầu ra là:
Info
sizeof(char) = 1
sizeof(wchar_t) = 2
LC_ALL = C
LC_CTYPE = C
----
cout : 핼로
wcout : ----
cout : おはよう。
wcout : ----
cout : ?好
wcout : ----
cout : resume
wcout : resume
----
cout : r?sum?
wcout : r?um
Một đầu ra với locale Hàn Quốc:
Info
sizeof(char) = 1
sizeof(wchar_t) = 2
LC_ALL = Korean_Korea.949
LC_CTYPE = Korean_Korea.949
----
cout : 핼로
wcout : 핼로
----
cout : おはよう。
wcout : おはよう。
----
cout : ?好
wcout : ----
cout : resume
wcout : resume
----
cout : r?sum?
wcout : resume
Một đầu ra:
Info
sizeof(char) = 1
sizeof(wchar_t) = 2
LC_ALL = fr-FR
LC_CTYPE = fr-FR
----
cout : CU·I
wcout : ----
cout : ªªªIªeª|¡£
wcout : ----
cout : ?u¿
wcout : ----
cout : resume
wcout : resume
----
cout : r?sum?
wcout : resume
Hóa ra Nếu tôi không cung cấp đúng ngôn ngữ, ứng dụng không xử lý phạm vi nhất định của nhân vật, không có vấn đề tôi sử dụng char hoặc wchar_t. Đó không chỉ là vấn đề. Visual studio đưa ra cảnh báo:
warning C4566: character represented by universal-character-name '\u4F60' cannot be represented in the current code page (949)
Tôi không chắc chắn nếu điều này mô tả những gì tôi nhận được là đầu ra hay cái gì khác.
Câu hỏi. Điều gì sẽ là thực hành tốt nhất và tại sao? Làm thế nào người ta có thể làm cho một nền tảng ứng dụng/thực hiện/quốc gia độc lập? những gì chính xác xảy ra với chuỗi chữ trên nguồn? giá trị chuỗi được giải thích bằng ứng dụng như thế nào?
Để có khả năng tương thích tối đa: Giữ các ký tự trong nguồn của bạn với các ký tự ASCII rất cơ bản. Sử dụng mã hóa UTF8 bằng cách sử dụng byte được xác định bằng \ x trong chuỗi. Công cụ u8 "\ u1234" mới trong phiên bản mới nhất của C++ sẽ làm cho việc này trở nên dễ dàng hơn, nhưng nó chưa được Visual Studio hỗ trợ. Xem thêm câu hỏi này: http://stackoverflow.com/questions/3768363/character-sets-not-clear – JCx
'TCHAR' s là một rắc rối khổng lồ. Trừ khi bạn đang tìm kiếm để hỗ trợ các phiên bản Windows thực sự cũ, chỉ cần cung cấp cho Windows chuỗi rộng. Để tương thích với những thứ khác, bạn có thể lưu trữ các chuỗi bằng cách sử dụng UTF-8 và chuyển đổi chúng khi sử dụng chức năng Windows API. – chris