2011-12-14 35 views
10

Để tìm hiểu xem C++ có phải là ngôn ngữ phù hợp cho một dự án của tôi hay không, tôi muốn thử nghiệm các khả năng UTF-8. Theo tài liệu tham khảo, tôi đã xây dựng ví dụ này:Xử lý UTF-8 trong C++

#include <string> 
#include <iostream> 

using namespace std; 

int main() { 
    wstring str; 
    while(getline(wcin, str)) { 
     wcout << str << endl; 
     if(str.empty()) break; 
    } 

    return 0; 
} 

Nhưng khi tôi gõ vào một ký tự UTF-8, nó đối xử tệ bạc:

$ > ./utf8 
Hello 
Hello 
für 
f 
$ > 

Không chỉ nó không in ü, nhưng cũng bỏ ngay. gdb nói với tôi rằng không có tai nạn, nhưng là một lối ra bình thường, nhưng tôi thấy khó tin.

+0

Bạn đang nhắm mục tiêu nền tảng nào (Windows, Linux, v.v ...)? –

+0

Linux, thực sự. Nếu nó hoạt động trên các cửa sổ, quá, đó là loại tiền thưởng. – Lanbo

+2

Ngôn ngữ của bạn có được đặt thành mã hóa UTF-8 không? –

Trả lời

8

Không sử dụng wstring trên Linux.

std::wstring VS std::string

Hãy xem câu trả lời đầu tiên. Tôi chắc chắn nó trả lời câu hỏi của bạn.

  1. Khi nào tôi nên sử dụng std :: wstring over std :: string?

Trên Linux? Hầu như không bao giờ (§).

Trên Windows? Gần như luôn luôn (§).

+0

+1: Hãy xem câu trả lời này. Tôi chắc chắn nó liên kết với một câu trả lời cho câu hỏi của bạn. – Klaim

+0

Trong nhận xét 'boost :: spirit' trên UTF-8, chúng luôn nói về việc sử dụng' wchar_t'. – Lanbo

+0

@ Scán: Tôi đoán họ sử dụng 'wchar_t' tất cả thời gian cho các điểm mã, được sử dụng khi dịch UTF8 đến và từ bất kỳ thứ gì. 'wchar_t' không phải là một nhân vật tốt cho UTF8. –

7

Bản thân ngôn ngữ không liên quan gì đến mã unicode hoặc bất kỳ mã ký tự nào khác. Nó được gắn với hệ điều hành. Windows sử dụng UTF16 cho hỗ trợ unicode có nghĩa là sử dụng ký tự rộng (ký tự rộng 16 bit) - wchar_t hoặc std: wstring. Mỗi chức năng Win Api hoạt động với các chuỗi yêu cầu đầu vào char rộng.

Nhưng các hệ thống dựa trên Unix, tức là Mac OS X hoặc Linux sử dụng UTF8. Tất nhiên - nó chỉ là vấn đề về cách bạn xử lý các byte trong mảng, vì vậy bạn có thể có chuỗi UTF16 được lưu trữ trong mảng C hoặc std: chuỗi chứa chung. Đây là lý do tại sao bạn không thấy bất kỳ wstrings trong mã cross-nền tảng; thay vào đó tất cả các chuỗi được xử lý như UTF8 và được mã hóa lại khi cần thiết để UTF16 (trên cửa sổ).

Bạn có nhiều tùy chọn hơn để xử lý công cụ này một chút khó hiểu. Cá nhân tôi làm như đã đề cập ở trên - bằng cách sử dụng đúng mã UTF8 trong tất cả các ứng dụng, mã hóa lại chuỗi khi tương tác với Windows Api và trực tiếp sử dụng chúng trên Mac OS X. Để giành lại mã hóa, tôi sử dụng những người trợ giúp chuyển đổi tuyệt vời:

C++ UTF-8 Conversion Helpers (trên MSDN, có sẵn theo Giấy phép Apache, Phiên bản 2.0).

Bạn cũng có thể sử dụng Chuỗi Qt đa nền tảng xác định chức năng chuyển đổi từ UTF8 đến/từ UTF16 và các mã khác (ANSI, La tinh ...).

Vì vậy, câu trả lời ở trên - sử dụng unix luôn UTF8 (std :: string, char), trên Windows UTF16 (std :: wstring, wchar_t) là đúng.

+0

Vậy bạn nên làm gì khi tôi muốn làm một trình biên dịch ngôn ngữ/phiên dịch xử lý mọi thứ như UTF-8 trên cả hai hệ thống? – Lanbo

+0

Vâng, không có câu trả lời đơn giản và giải pháp "tối thượng". Nó phụ thuộc vào trình biên dịch, IDE và API bạn sử dụng. Tôi khuyên bạn nên sử dụng một số khung ứng dụng đa nền tảng, lý tưởng là Qt của Nokia - http://qt.nokia.com. Nó hoàn toàn miễn phí cho các dự án mã nguồn mở và thậm chí cho các dự án thương mại - nếu bạn đảm bảo tuân thủ Giấy phép Công cộng GNU (LGPL). – vitakot

3

Hãy nhớ rằng khi khởi động chương trình chính, ngôn ngữ "C" được chọn làm mặc định. Bạn có thể không muốn điều này nếu bạn xử lý utf-8. Gọi số setlocale(LC_CTYPE, "") sẽ tắt mặc định này và bạn nhận được bất kỳ thứ gì được xác định trong môi trường (có lẽ là một ngôn ngữ utf-8).

+1

Có! Trái ngược với một số câu trả lời khác, nó hoàn toàn OK để sử dụng 'wchar_t' trên Linux. Bạn hoàn toàn phải sử dụng đúng ngôn ngữ mặc dù. –