2011-01-06 339 views
4

我的std :: strings以UTF-8编码,因此std :: string <运算符不会剪切它。我怎么能比较2 utf-8编码的std :: strings?排序UTF-8字符串?

它不会削减它是口音,E排Z中后,它不应该

感谢

+1

为什么不标准的`运<`不是“剪”?你想要什么样的订单? – 2011-01-06 02:45:52

+1

UTF-8编码的字符串按照与等效的UTF-32编码字符串相同的顺序排序。 – dan04 2011-01-06 02:46:32

回答

4

如果你不想要一个字典排序(这是什么排序UTF-8编码字符串按字典顺序会给你),那么你将需要将你的UTF-8编码的字符串解码为适当的UCS-2或UCS-4,并应用你选择的适当的比较函数。

要重申一点,UTF-8编码的机制被巧妙地设计成这样,如果您排序通过查看每个8位编码字节的数值,您将得到相同的结果,如果你第一次解码将字符串转换为Unicode并比较每个代码点的数字值。

更新:您的更新问题表明您想要比纯粹的词典排序更复杂的比较功能。您将需要解码您的UTF-8字符串并比较解码的字符。

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