2012-10-04 10 views
7

Tôi bắt đầu viết một ứng dụng thao tác văn bản rất cơ bản trong Qt, không có GUI. Văn bản của tôi chứa các ký tự đặc biệt, nhưng bằng cách nào đó tôi không thể in các ký tự đặc biệt đó, bất kể tôi đã làm gì. Sau đó, tôi nhận thấy rằng sau khi thêm một cá thể QCoreApplication (mà trước đây tôi đã xóa, vì tôi nghĩ mình không cần nó), mọi thứ hoạt động bình thường.Tại sao QString không xử lý các ký tự đặc biệt một cách chính xác, khi không có ứng dụng QCoreApplication được khởi tạo?

Đây là mã:

#include <QCoreApplication> 
#include <QString> 
#include <QDebug> 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    QString s(QString::fromUtf8("aä\xc3\xa4")); // aää 

    qDebug() << s; 
    qDebug() << s.toAscii(); 
    qDebug() << s.toLatin1(); 
    qDebug() << s.toUtf8(); 
    qDebug() << s.toLocal8Bit(); 
    qDebug("%s", qPrintable(s)); 

    qDebug("%i", s.length()); 
    qDebug("%i", strlen(qPrintable(s))); 

    return 0; 
} 

Output với QCoreApplication (mọi thứ hoạt động như mong muốn):

"aää" 
"aää" 
"aää" 
"aää" 
"aää" 
aää 
3 
5 

Output sau khi cho ý kiến ​​ra đường, nơi QCoreApplication được định nghĩa (ký tự đặc biệt không được hiển thị nữa):

"a" 
"a" 
"a" 
"a" 
"a" 
a 
3 
1 

Lưu ý rằng sau khi gọi qPrintabable(s), các ký tự đặc biệt đã bị xóa. Tôi đã thử nghiệm điều này để đảm bảo rằng QDebug không phải là vấn đề.

Tôi cũng đã kiểm tra xem tệp có thực sự được mã hóa trong UTF-8 hay không.

Tại sao QString không xử lý các ký tự đặc biệt một cách chính xác khi không có QCoreApplication được khởi tạo?

+0

Câu hỏi thú vị thú vị ... Tôi đoán rằng lý do có thể nằm trong 'QTextCodec' hoặc' QTextStream', nhưng tôi có thể sai. 'QDebug' sử dụng' QTextStream', nhưng như bạn đã nhận thấy, 'qPrintable' (chỉ là viết tắt của' .toLocal8Bit(). ConstData() ') đã loại bỏ một cách kỳ diệu các ký tự không phải ascii của bạn, hoặc chèn một' '\ 0'', vì đây là giải thích duy nhất tại sao 'strlen' nên trả về 1. – leemes

+0

Chèn'' \ 0'' không phải là trường hợp, vì tôi đã thử nghiệm các chuỗi khác là '" aäa "', trong đó các chữ cái khác theo sau sau một nhân vật đặc biệt. Chúng không bị loại bỏ. Nói cách khác, nếu 's' là' "aäa" ', đầu ra khi không sử dụng' QCoreApplication' là '" aa "'. – Misch

Trả lời

7

Sau khi đi qua mã nguồn Qt, tôi tình cờ mã này gọi khi QCoreApplication được xây dựng:

#ifdef Q_OS_UNIX 
    setlocale(LC_ALL, "");    // use correct char set mapping 
    qt_locale_initialized = true; 
#endif 

Nói cách khác, trên các hệ thống "Unix", các nhà xây dựng QCoreApplication đang thực hiện một cuộc gọi đến setlocale (tìm thấy trong locale.h), được sử dụng để đặt ngôn ngữ hiện tại của chương trình. Điều này cuối cùng ảnh hưởng đến đầu ra từ qDebug, dựa trên QTextStream, mà cuối cùng sử dụng những gì nó tin là miền địa phương được hệ thống xác định để tạo ra đầu ra của nó.

Khi tôi kiểm tra mã của bạn trên hệ thống Linux, tôi đã gặp phải kết quả tương tự như bạn đã làm. Trên hệ thống Windows, nhận xét rằng việc xây dựng QCoreApplication không ảnh hưởng đến kết quả. Tôi cũng nhận thấy rằng việc in ra chuỗi gốc thông qua printf đã cho kết quả chính xác bất kể là QCoreApplication đã được tạo chưa.

+0

vì vậy đây có phải là lỗi hay không Qt chỉ định rằng người ta phải khởi tạo ứng dụng 'Q (Lõi)' trước khi sử dụng các thành phần hoặc lớp học khác của Qt? – Misch

+0

@Misch Qt chỉ định các điều kiện mà theo đó người ta phải khởi tạo ứng dụng Q (Lõi). Tham khảo http://qt-project.org/doc/qt-4.8/qcoreapplication.html. Hành vi cụ thể này được ghi lại trong phần "Cài đặt miền địa phương". –

Các vấn đề liên quan