Nếu bạn nạp một giá trị số wchar_t
, char16_t
hoặc char32_t
vào một luồng hẹp, nó sẽ in giá trị số của điểm mã.iostreams - In giá trị `wchar_t` hoặc` charXX_t` thành một ký tự
#include <iostream>
using std::cout;
int main()
{
cout << 'x' << L'x' << u'x' << U'x' << '\n';
}
in x120120120
. Điều này là do có một số operator<<
cho sự kết hợp cụ thể của basic_ostream
với số charT
, nhưng không có toán tử tương tự cho các loại ký tự khác, vì vậy chúng được chuyển thành âm thầm thành int
và được in theo cách đó. Tương tự, xâu phi hẹp (L"x"
, u"x"
, U"X"
) sẽ được âm thầm chuyển đổi sang void*
và in như giá trị con trỏ, và không hẹp chuỗi đối tượng (wstring
, u16string
, u32string
) thậm chí sẽ không biên dịch.
Vì vậy, câu hỏi: cách khủng khiếp nhất để in một, char16_t
, hoặc giá trị wchar_t
char32_t
trên ostream hẹp, như nhân vật, chứ không phải là giá trị số của điểm mã là gì? Nó phải chuyển đổi một cách chính xác tất cả các điểm mã hóa có thể thể hiện được trong mã hóa của ostream, tới mã hóa đó và sẽ báo cáo lỗi khi điểm mã hóa không thể biểu diễn được. (Ví dụ, được đưa ra u'…'
và một dòng chảy UTF-8, chuỗi ba byte 0xE2 0x80 0xA6 phải được ghi vào luồng; nhưng được đưa ra u'â'
và một dòng KOI8-R, một lỗi nên được báo cáo.)
Tương tự , làm thế nào có thể in một chuỗi C-string hoặc đối tượng chuỗi không hẹp trên một ostream hẹp, chuyển đổi sang mã hóa đầu ra?
Nếu không thể thực hiện việc này trong ISO C++ 11, tôi sẽ trả lời theo từng nền tảng cụ thể.
(Lấy cảm hứng từ this question.)
Tóm lại, bạn phải 1) sử dụng một dòng rộng hoặc 2) chuyển đổi dữ liệu ký tự rộng sang mã hóa hẹp chính bạn (đó là một chuyển đổi có thể mất). Một ostream không thể thực hiện chuyển đổi đó cho bạn. Xem ['std :: wstring_convert'] (http: //en.cppreference.com/w/cpp/locale/wstring_convert) hoặc sử dụng thư viện như [ICONV] (https://www.gnu.org/software/libiconv/) hoặc [ICU] (http: //site.icu-project. org /). –