2011-01-06 15 views
4

私のstd :: stringsはUTF-8でエンコードされるので、std :: string <演算子はそれをカットしません。 2つのutf-8でエンコードされたstd :: stringsをどのように比較できますか?UTF-8文字列をソートする?

それがアクセントのためにあるカットしない場合、Eは、それはすべきではない

zの後に来るのおかげ

+1

/&ペーストをコピーする簡単なはずの小さなラッパを持っていますか?何を注文しますか? –

+1

UTF-8でエンコードされた文字列は、同等のUTF-32でエンコードされた文字列と同じ順序でソートされます。 – dan04

+2

@Charles:私はそれが単にバイト単位の比較を実行し、アクセントなどを考慮しないので、「カット」しないと信じています。 – Mehrdad

答えて

4

あなたは、エンコードされたUTF-8にソートされているもの辞書式順序を(したくない場合UTF-8でエンコードされた文字列を適切にUCS-2またはUCS-4にデコ​​ードし、適切な比較関数を適用する必要があります。

UTF-8エンコーディングの仕組みは巧みに設計されており、8ビットのエンコードされた各バイトの数値を並べ替えた場合、と同じが最初にデコードされたようになります文字列をUnicodeに変換し、各コードポイントの数値を比較します。

更新:更新された質問は、純粋に辞書編集の並べ替えよりも複雑な比較機能が必要であることを示しています。 UTF-8文字列をデコードし、デコードされた文字を比較する必要があります。

+0

UTF-16エンコーディングはその機能を持っていないことに注意してください。 – dan04

+0

@ dan04:どのような機能がありませんか? –

+3

バイト配列ANSIスタイルとして扱わない限り、照合(ソート)とエンコーディングは全く別の2つの問題です。 http://www.joelonsoftware.com/articles/Unicode.html –

6

標準で照合(ソート)などのロケール固有のものについては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::collate<>::compare(a, b) < 0ラッパーをなくし、std::locale::operator()(a, b)が存在していることを私の注意に持って来られています。

#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; 
}