我有一个C ++应用程序,它使用STL集来保存字符串列表(有序和唯一)。
我遇到的问题是下划线的顺序与我需要的相反。
示例STL顺序:
"word0"
"word_"
我需要的订单是:
"word_"
"word0"
我已经开始实现自定义比较功能来处理这个问题,但我宁愿使用STL中提供的解决方案(如果有的话)。
在线搜索,我发现了一些对这个完全相同问题的引用,但在其他系统中,解决方案似乎是更改Collation或Locale,但我似乎无法找到如何使用STL
答案 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,至少在没有很多痛苦的情况下也是如此。您 将无法使用
cout
和char_traits
等普通流对象。
他接着列举了为什么修改{{1}}以执行此比较不是一个好主意的几个其他正当理由。
我强烈建议您阅读Austern的论文。
答案 2 :(得分:3)
您可以将std::lexicographic_compare
与自定义谓词一起使用来比较字符串与自定义字符顺序 - 正如Gnawme已经说过的那样。以下代码汇总了std::set
和std::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 ++库中的字符串类不提供任何区域设置敏感的字符串比较服务。”因此,您还需要将语言环境用法包装在单独的比较函数中。
因此,如果现有的语言环境没有按照您喜欢的方式比较字符串,那么这种方式看起来就像是一种过度杀伤。