2016-02-24 7 views
1

Мне нужно сравнить две кодированные строки UTF-8, содержащие символы макрона (À, Ō, Ū). Заказ должен быть < < Ā О < < Ō U < Ū смысл, что символы Macron не следует сравнивать на основе их числовое значение (А < < O U < < Ā Ō < U), но лексически.Различные результаты localeAwareCompare

Для того, чтобы достичь этого, я попытался с помощью localeAwareCompare:

QString a = QString::fromUtf8("Ā"); 
QString b = QString::fromUtf8("O"); 
int result = QString::localeAwareCompare(a, b); 

С этим куском кода я встречая другое поведение на моем настольном компьютере под управлением Mac OS и Android. На настольном компьютере результат равен -1 (что верно, потому что Ā < O), в то время как андроид дает 117 (что неверно).

документация Qt для localeAwareCompare содержит следующее замечание:

The comparison is performed in a locale- and also platform-dependent manner. 

по умолчанию локали на устройствах я использую являются:

  • Mac OS:
    • Имя: en_US
    • Сценарий: 7
    • Страна: UnitedStates
  • Android:
    • Название: ""
    • Автор сценария: 0
    • Страна: AnyCountry

Ручная настройка локали по умолчанию en_US делает нет помощи. Я только предполагаю, что это связано с зависимостью платформы.

Здесь я затрудняюсь. Правильно ли это поведение? Если да, существует ли еще один способ вычисления желаемого сравнения?


Пример

#include <QApplication> 
#include <QString> 
#include <QDebug> 

int main(int argc, char** argv) { 
    QApplication app(argc, argv); 

    QString a = QString::fromUtf8("A"); 
    QString a_m = QString::fromUtf8("Ā"); 
    QString o = QString::fromUtf8("O"); 

    qDebug() << (QString::localeAwareCompare(a, a_m) < 0 ? "A < Ā" : "Ā < A"); 
    qDebug() << (QString::localeAwareCompare(a_m, o) < 0 ? "Ā < O" : "O < Ā"); 

    return app.exec(); 
} 
+0

Какие Qt версии вы используете? [Это сообщение SO] (http://stackoverflow.com/questions/3773914/why-isnt-qstringlocaleawarecompare-working-correctly) показывает, что некоторые версии Qt, по-видимому, сломаны. Я проверил ваш пример с Qt 4.8.6, а также с Qt 5.2.1 и получил разные результаты. – mindriot

+0

Я использую Qt 5.5.1. Что значит «разные результаты»? Получаете ли вы правильный результат? NRiesterer

+0

Хм, честно говоря, я всегда получаю -1 на Qt5, но я получаю -79 на Qt4, если не добавить оператор 'QLocale :: setDefault()'. Если я добавлю это, я получу -1 на Qt4. Но мой код, вероятно, тоже отличается от вашего. Можете ли вы опубликовать [минимальный, полный и проверяемый пример] (http://stackoverflow.com/help/mcve)? – mindriot

ответ

0

Вы можете удалить macrons де-образующую строку:

QString a = QString::fromUtf8("Ā"); 
QString norm = a.normalized(QString::NormalizationForm_D); 
QString aOut; 
// Remove all marks 
Q_FOREACH(QChar ch, norm){ 
    QChar::Category c = ch.category(); 
    if (c != QChar::Mark_Enclosing && 
     c != QChar::Mark_NonSpacing && 
     c != QChar::Mark_SpacingCombining){ 
      aOut.append(ch); 
    } 
} 
qDebug() << aOut; // prints "A" 

Затем сравните строки обычно. Однако это также приведет к разрыву графов, таких как Æ. Для этого потребуется более сложный алгоритм.

Для справки: http://doc.qt.io/qt-5/qstring.html#normalized