如何更改STL中下划线的排序顺序?

时间:2011-11-17 20:01:46

标签: c++ sorting stl

我有一个C ++应用程序,它使用STL集来保存字符串列表(有序和唯一)。

我遇到的问题是下划线的顺序与我需要的相反。

示例STL顺序:

"word0"
"word_"

我需要的订单是:

"word_"
"word0"

我已经开始实现自定义比较功能来处理这个问题,但我宁愿使用STL中提供的解决方案(如果有的话)。

在线搜索,我发现了一些对这个完全相同问题的引用,但在其他系统中,解决方案似乎是更改Collat​​ion或Locale,但我似乎无法找到如何使用STL

4 个答案:

答案 0 :(得分:7)

此特定问题没有内置解决方案,因为库希望您构建自己的自定义比较器来处理此问题。

但是,您可能需要考虑定义自己的char_traits类型,这样可以自定义字符串的排序和比较方式。虽然没有最好的在线教程,但这可能是解决您问题的最简洁,最简单的解决方案。作为一个无耻的插件,我写了一个 this earlier question about char_traits 的答案,这可能对你正在做的事情有用。

我建议你不要乱用语言环境。区域设计旨在用于本地化,旨在对文本的处理方式产生巨大而深远的影响。自定义比较器或新的char_traits类型更直接地解决了手头的问题。

答案 1 :(得分:4)

Matt Austern写了一篇关于"How to do case-insensitive string comparison"的论文,它正确地处理了语言环境。它可能包含您正在寻找的语言环境和方面的信息。

否则,如果您只是想要反转几个字符的通常比较顺序,那么不应该使用std::lexicographical_compare和您自己的比较函数对象来完成这项工作吗?

bool mycomp( char c1, char c2 )
{
    // Return 0x5F < 0x30
    if ( ( c1 == '_' ) && ( c2 == '0' ) )
        return true;
    if ( ( c1 == '0' ) && ( c2 == '_' ) )
        return false;

    return ( c1 < c2 );
}

std::string w1 = "word0";
std::string w2 = "word_";

bool t1 = std::lexicographical_compare( w1.begin(), w1.end(), w2.begin(), w2.end() );
bool t2 = std::lexicographical_compare( w1.begin(), w1.end(), w2.begin(), w2.end(), mycomp );

"word0"在第一种情况下评估小于"word_",在第二种情况下评估小于char_traits,这就是你所追求的。

如果你已经做了类似的事情,这是最简单的方法。

修改:关于使用std::string来完成此任务的主题,Austern的文章指出:

  

标准库类型<使用traits参数   所有比较,通过提供具有相等性的traits参数   少于适当重新定义,你可以实例化basic_string   这样一来,==cin运算符可以满足您的需求。您   可以做到,但这不值得麻烦。

     

你将无法进行I / O,至少在没有很多痛苦的情况下也是如此。您   将无法使用coutchar_traits等普通流对象。

他接着列举了为什么修改{{1}}以执行此比较不是一个好主意的几个其他正当理由。

我强烈建议您阅读Austern的论文。

答案 2 :(得分:3)

您可以将std::lexicographic_compare与自定义谓词一起使用来比较字符串与自定义字符顺序 - 正如Gnawme已经说过的那样。以下代码汇总了std::setstd::lexicographic_compare

#include <iostream>
#include <set>
#include <string>
#include <algorithm>

struct comp
{
    static bool compchar(char a, char b)
    {
        if (a == '0' && b == '_' || a == '_' && b == '0')
            return !(a < b);
        else
            return (a < b);
    }

    bool operator()(const std::string& a, const std::string& b) const
    {
        return std::lexicographical_compare(a.begin(), a.end(),
                                            b.begin(), b.end(),
                                            compchar);
    }
};

int main()
{
    std::set<std::string, comp> test;
    test.insert("word0");
    test.insert("word_");

    for (std::set<std::string, comp>::const_iterator cit = test.begin();
         cit != test.end(); ++cit)
         std::cout << *cit << std::endl;

    return 0;
}

答案 3 :(得分:1)

有一个collate类,这里是C ++中的brief explanations of facet usage,其中包含一些如何使用它的示例。

但是你可能需要自己实现实际的逻辑。

并且:“标准C ++库中的字符串类不提供任何区域设置敏感的字符串比较服务。”因此,您还需要将语言环境用法包装在单独的比较函数中。

因此,如果现有的语言环境没有按照您喜欢的方式比较字符串,那么这种方式看起来就像是一种过度杀伤。