Сортировка строк UTF-8? - PullRequest
       3

Сортировка строк UTF-8?

4 голосов
/ 06 января 2011

Мои std :: strings кодируются в UTF-8, поэтому оператор std :: string <не обрезает их.Как я могу сравнить 2 stf :: strings в кодировке utf-8? </p>

там, где он не вырезан, для акцентов, é следует после z, которого не должно быть

Спасибо

Ответы [ 4 ]

6 голосов
/ 06 января 2011

В стандарте есть std::locale для определенных для локали вещей, таких как сортировка (сортировка).Если среда содержит LC_COLLATE=en_US.utf8 или подобное, эта программа будет сортировать строки по желанию.

#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <locale>
#include <string>
#include <vector>
class collate_in : public std::binary_function<std::string, std::string, bool> {
  protected:
    const std::collate<char> &coll;
  public:
    collate_in(std::locale loc)
        : coll(std::use_facet<std::collate<char> >(loc)) {}
    bool operator()(const std::string &a, const std::string &b) const {
        // std::collate::compare() takes C-style string (begin, end)s and
        // returns values like strcmp or strcoll.  Compare to 0 for results
        // expected for a less<>-style comparator.
        return coll.compare(a.c_str(), a.c_str() + a.size(),
                            b.c_str(), b.c_str() + b.size()) < 0;
    }
};
int main() {
    std::vector<std::string> v;
    copy(std::istream_iterator<std::string>(std::cin),
         std::istream_iterator<std::string>(), back_inserter(v));
    // std::locale("") is the locale from the environment.  One could also
    // std::locale::global(std::locale("")) to set up this program's global
    // first, and then use locale() to get the global locale, or choose a
    // specific locale instead of using the environment's.
    sort(v.begin(), v.end(), collate_in(std::locale("")));
    copy(v.begin(), v.end(),
         std::ostream_iterator<std::string>(std::cout, "\n"));
    return 0;
}
$ cat >file
f
é
e
d
^D
$ LC_COLLATE=C ./a.out file
d
e
f
é
$ LC_COLLATE=en_US.utf8 ./a.out file
d
e
é
f

Мне стало известно, что существует std::locale::operator()(a, b), исключая std::collate<>::compare(a, b) < 0обертка, которую я написал выше.

#include <algorithm>
#include <iostream>
#include <iterator>
#include <locale>
#include <string>
#include <vector>
int main() {
    std::vector<std::string> v;
    copy(std::istream_iterator<std::string>(std::cin),
         std::istream_iterator<std::string>(), back_inserter(v));
    sort(v.begin(), v.end(), std::locale(""));
    copy(v.begin(), v.end(),
         std::ostream_iterator<std::string>(std::cout, "\n"));
    return 0;
}
5 голосов
/ 06 января 2011

Если вы не хотите лексикографического упорядочения (то, что даст вам сортировка строк в кодировке UTF-8, что даст вам лексикография), вам нужно будет декодировать строки в кодировке UTF-8 в UCS-2 или UCS-4 как и примените подходящую функцию сравнения по вашему выбору.

Чтобы повторить эту мысль, механизм кодирования UTF-8 разработан с умом, так что если вы сортируете, глядя на числовое значение каждого 8-битного кодированного байта, вы получите такой же результат, как если бы Вы сначала расшифровали строку в Unicode и сравнили числовые значения каждой кодовой точки.

Обновление: Ваш обновленный вопрос указывает на то, что вам нужна более сложная функция сравнения, чем просто лексикографическая сортировка. Вам нужно будет декодировать строки UTF-8 и сравнить декодированные символы.

1 голос
/ 06 января 2011

Кодирование (UTF-8, 16 и т. Д.) Не является проблемой, имеет значение вопрос о том, обрабатывает ли сам контейнер строку как строку Unicode или 8-битную (ASCII или Latin-1) строку.

Я нашел Существует ли дружественный STL и UTF-8 C ++ Wrapper для ICU или другая мощная библиотека Unicode , которая может вам помочь.

0 голосов
/ 04 ноября 2015

Одним из вариантов может быть использование средств сортировки ICU (http://userguide.icu -project.org / collation / api ), которые предоставляют правильно интернационализированный метод сравнения, который затем можно использовать для сортировки.

Chromium имеет небольшую оболочку, которую легко скопировать и вставить / использовать повторно

https://code.google.com/p/chromium/codesearch#chromium/src/base/i18n/string_compare.cc&sq=package:chromium&type=cs

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...