Trước khi tiếp tục, tôi nên đề cập rằng những gì bạn đang làm không tuân thủ c/C++. Các trạng thái specification trong 2.2 bộ ký tự nào hợp lệ trong mã nguồn. Nó không có nhiều trong đó, và tất cả các nhân vật được sử dụng là trong ascii. Vì vậy, ... Tất cả mọi thứ dưới đây là về một thực hiện cụ thể (như nó xảy ra, VC2008 trên một máy địa phương của Mỹ).
Để bắt đầu, bạn có 4 ký tự trên dòng cout
và 4 glyphs trên đầu ra. Vì vậy, vấn đề không phải là một trong những mã hóa UTF8, vì nó sẽ kết hợp nhiều ký tự nguồn để ít glyphs.
Từ bạn nguồn chuỗi để hiển thị trên giao diện điều khiển, tất cả những thứ đó đóng một vai trò:
- gì mã hóa tập tin nguồn của bạn là trong (tức là cách C++ tập tin của bạn sẽ được nhìn thấy bởi trình biên dịch)
- gì trình biên dịch của bạn không có một chuỗi chữ, và những gì nguồn mã hóa nó hiểu
- cách của bạn
<<
giải thích chuỗi mã hóa bạn đang đi qua trong
- gì mã hóa các giao diện điều khiển hy vọng
- cách giao diện điều khiển dịch đầu ra thành phông chữ.
Bây giờ ...
1 và 2 là những thứ khá dễ dàng. Dường như trình biên dịch đoán định dạng tệp nguồn là gì và giải mã nó thành biểu diễn bên trong của nó. Nó tạo ra chuỗi dữ liệu tương ứng bằng chữ trong bảng mã hiện tại bất kể mã hóa nguồn là gì. Tôi đã không tìm thấy chi tiết/kiểm soát rõ ràng về điều này.
3 thậm chí còn dễ dàng hơn. Ngoại trừ mã kiểm soát, <<
chỉ chuyển dữ liệu xuống cho char *.
4 được điều khiển bởi SetConsoleOutputCP
. Nó sẽ mặc định để mã hóa hệ thống mặc định của bạn. Bạn cũng có thể tìm ra cái nào bạn có với GetConsoleOutputCP
(đầu vào được điều khiển khác nhau, thông qua SetConsoleCP
)
5 là một điều thú vị. Tôi đập đầu của tôi để tìm ra lý do tại sao tôi không thể có được é để hiển thị đúng cách, sử dụng CP1252 (Tây Âu, cửa sổ). Nó chỉ ra rằng phông chữ hệ thống của tôi không có glyph cho nhân vật đó, và cẩn thận sử dụng glyph của mã chuẩn của tôi (vốn Theta, tôi sẽ nhận được nếu tôi không gọi SetConsoleOutputCP). Để khắc phục nó, tôi đã phải thay đổi phông chữ mà tôi sử dụng trên bảng điều khiển sang Bảng điều khiển Lucida (một phông chữ loại thực).
Một số điều thú vị tôi học kinh nghiệm nhìn này:
- mã hóa của nguồn không quan trọng, miễn là trình biên dịch có thể hình dung nó ra (đáng chú ý, thay đổi nó để UTF8 không thay đổi mã được tạo Chuỗi "é" của tôi vẫn được mã hóa với CP1252 là
233 0
)
- VC đang chọn một mã mã cho các chuỗi ký tự mà tôi dường như không kiểm soát được.
- kiểm soát những gì giao diện điều khiển chương trình là đau đớn hơn những gì tôi đã mong
... Vì vậy, điều này có nghĩa đối với bạn? Dưới đây là một số lời khuyên:
- không sử dụng non-ascii trong chuỗi ký tự chuỗi. Sử dụng tài nguyên, trong đó bạn kiểm soát mã hóa.
- đảm bảo bạn biết bảng điều khiển của mình mong đợi mã hóa nào và phông chữ của bạn có glyph để thể hiện các ký tự bạn gửi.
- nếu bạn muốn tìm ra mã hóa nào đang được sử dụng trong trường hợp của bạn, tôi khuyên bạn nên in giá trị thực của ký tự dưới dạng số nguyên.
char * a = "é"; std::cout << (unsigned int) (unsigned char) a[0]
hiển thị 233 cho tôi, điều này xảy ra là mã hóa trong CP1252.
BTW, nếu bạn nhận được "ÓÚÛ¨" thay vì những gì bạn dán, thì có vẻ như 4 byte của bạn được diễn giải ở đâu đó là CP850.
Bạn có thể cung cấp cho chúng tôi thêm một chút đầu vào hay không. Điều này có xảy ra cho đầu ra xây dựng, tất cả đầu ra hay cái gì khác không? Bạn có thể cho chúng tôi một hoạt động cụ thể mà điều này xảy ra (xây dựng, gỡ lỗi, v.v ...) – JaredPar
Có, vui lòng hiển thị ví dụ về những gì bạn nghĩ sẽ xuất hiện và những gì thực sự xuất hiện. – wallyk
Điều gì xảy ra nếu bạn sử dụng wcout? – Naveen