2010-10-30 89 views
5

检查下面的代码:对STL使用比较设置

string toLowerCase(const string& str) { 
    string res(str); 
    int i; 

    for (i = 0; i < (int) res.size(); i++) 
     res[i] = (char) tolower(res[i]); 

    return res; 
} 

class LeagueComparator 
{ 
public: 
    bool operator()(const string& s1, const string& s2) 
    { 
     return toLowerCase(s1) < toLowerCase(s2); 
    } 
}; 

int main() 
{ 
    set<string, LeagueComparator> leagues; 
    set<string, LeagueComparator>::iterator iter; 

    leagues.insert("BLeague"); 
    leagues.insert("aLeague"); // leagues = {"aLeague", "BLeague"} 
    leagues.insert("ALeague"); 

    for (iter = leagues.begin(); iter != leagues.end(); iter++) 
     cout << *iter << endl; 

    return 0; 
} 

输出是:

aLeague 
BLeague 

这让我震惊。我认为(和预期)的输出将是:

aLeague 
ALeague 
BLeague 

leagues.insert("ALeague");执行之前,leagues包含"aLeague""BLeague"。我的问题是,当执行leagues.insert("ALeague");为什么机器对待"ALeague" == "aleague"?根据我的理解,leagues中没有元素"ALeague"。所以"ALeague"应该插入leagues。比较器应该确定在哪里放"ALeague"

在此先感谢。 PS:请不要打我使用C风格演员。 :P我懒得输入static_cast

+0

这感觉,你必须努力执行的C++风格的转换是主要原因C++风格转换的一个存在的事实 - 即你应该避免任何形式的铸造在C++中。在这种情况下,您应该完全删除这些转换,然后使用正确的类型。即而不是'(int)res.size()',删除转换并将'i'的类型改为'unsigned'。 – 2010-10-30 06:06:09

+0

另外,'i'应该在循环中声明,而不是在循环之外。在C++中,toLowerCase可能应该调用'std :: transform(str.begin(),str.end(),str.begin(),std :: ptr_fun(tolower))'而不是编写显式循环。 – 2010-10-30 06:11:17

+0

@Billy ONeal:谢谢。我需要使用'transform()'。 “toLowerCase”是我多年前写的。我想我当时并不知道“变革”。我会更新我的代码库。 – Donotalo 2010-10-30 17:30:13

回答

14

你的比较,由于toLowerCase,说,"aLeague" == "ALeague"。由于(根据您的比较)"aLeague" < "ALeague" == false"ALeague" < "aLeague" == false,它们必须是相同的。而插入一个等价的元素到一个集合中并不会做任何事情。

+3

+1。请注意,比较器不是建立平等,而是建立等值。 w.r.t有区别。标准和STL文档。 – 2010-10-30 06:10:21

+0

谢谢,编辑我的帖子。 – 2010-10-30 06:25:07

3

给你提供的比较,“澳大利亚职业足球联赛”的确是相当于“澳大利亚职业足球联赛”。

给定两个值,x和y,以及一个小比较器Z:

  • 如果Z(X,Y)为真,则x是小于y
  • 如果Z(Y, x)为真,则y小于x
  • 如果两者都不正确,那么x等于y
  • 如果两者均为true,则表示比较器已损坏。
+0

+1,但第三个子弹w.r.t略有问题。 STL文档。平等和等同是有区别的。小于比较者不能建立平等,只能等价。 – 2010-10-30 06:09:00

+0

@Billy ONeal:根据STL doc(我没有),“平等”和“等价”的定义是什么? – Donotalo 2010-10-30 17:34:36

+0

@Donotalo:使用相等比较器或运算符=='进行比较。如同在这里指定的那样,等价性是指一个小于比较器或'运算符<'的参数排序返回false的状态。从概念上讲,这是[可比的平等](http://www.sgi.com/tech/stl/EqualityComparable.html)和[小于可比的]之间的差异(http://www.sgi.com/tech/stl/ LessThanComparable.html)。 – 2010-10-30 17:50:28

4

当您向集合中插入任何值时,该对象将检查它是否已包含该值。您的LeagueComparator对象将ALeague与集合中已有的其他两个值进行比较。它确定现有值aLeague既不大于也不小于建议的新条目(ALeague),因此它们必须相等,因此它不会继续插入。该集只剩下两个元素。这就是提供客户比较对象的重点,所以您可以控制集合如何确定两个元素是否匹配。

+0

+1。请注意,为了与STL文档保持一致,此处的“平等”的大多数用法应替换为“等效”。少于比较者不能建立平等。 – 2010-10-30 06:09:41

0

替换您LeagueComparator

class LeagueComparator 
{ 
public: 
    bool operator()(const string& s1, const string& s2) 
    { 
     return toLowerCase(s1) < toLowerCase(s2) || 
       !(toLowerCase(s2) < toLowerCase(s1)) && s1 < s2; 
    } 
}; 
+0

这相当于完​​全不指定比较器。在任何情况下,您的比较器都会简单地返回s1 2010-10-30 17:54:22

+0

这是不正确的。 's1 =“b”','s2 =“A”'。由于“false”,我的比较器返回“false” !true && true = false'。 's1 2010-10-31 15:59:45