2011-04-26 103 views
7

目前試圖排序對象的矢量,其中每個對象包含字符串,在C++重載對比操作者在C++中的結果「無效操作者<」

的字符串可以包含字母或數字(由於設計限制,這是必要的,因爲可以改變比較器)。

此刻,對象的類被重載,因此當兩個對象進行比較時,它們所包含的字符串將進行比較。這可以起到一定的作用 - 然而,當我使用排序操作(如STL排序)來排列對象時,它會按順序排序三個字符串,例如「1」,「4」,「12」 「1」,「12」,「4」。 4大於12,但由於它從最左邊的數字開始比較,所以發生這種「不正確的」排序。

我最初的反應是改變我如何重載比較操作。我會首先檢查我正在比較的字符串的長度 - 如果字符串的內容更大或更小,這將是一個指示符號。

// overloaded comparision operators 
friend bool operator<(const nodeRecord & record1, const nodeRecord & record2){ 
    // we need to deal with strings of different lengths... 
    if(record1.comparator.length() < record2.comparator.length()) 
     return true; 
    else 
     return (record1.comparator < record2.comparator); 
} 

此操作在運行時會產生「表達式:無效的運算符<」消息。

有關我在哪裏犯錯的任何想法?看起來,我應該能夠向操作指示我想要如何進行排序操作 - 即使它無效,因爲我當前正在使用矢量來包含對象。在nodeRecord對象的初始化過程中

比較:

nodeRecord(int fromNode, int toNode, int connectionCost, bool compareByCost = false){ 
    // take the provided stock information and insert it into the object 
    stringstream fromNodeSS; 
    fromNodeSS << fromNode; 
    this->fromNode = fromNodeSS.str(); 
    stringstream toNodeSS; 
    toNodeSS << toNode; 
    this->toNode = toNodeSS.str(); 
    this->connectionCost = connectionCost; 

    // set the comparator to our chosen comparision term 
    if (!compareByCost){ 
     this->comparator = this->fromNode; // we use from node in this case, since we build the tree outwards 
    } 
    else{ 
     stringstream ss; 
     ss << this->connectionCost; 
     this->comparator = ss.str(); // we use the connection cost in this case, to allow us to sort new connections 
    } 

    // set this as a non-null (active) record 
    this->nullRecord = false; 
} 
+0

有什麼比較?發佈代碼。 – 2011-04-26 05:29:50

+0

你能不能顯示比較器的定義? – 2011-04-26 05:45:09

+0

@Mike和@Mario - 比較器在初始化nodeRecord對象期間初始化。你可以看到上面的內容。 – BSchlinker 2011-04-26 05:50:31

回答

10

您的操作員實際上是無效的。

如果您希望它可用於排序,則運算符<必須具有許多數學屬性。一個是反對稱性質:

x < y => !(y < x)

讓我們來定義x = "b"y = "aa"

  • x < y由於"b"長度不如的"aa"
  • y < x"aa"因爲長度不如"b"

坎?

另請注意,如果數字的前綴爲0 s,那麼您的定義很奇怪。

哦,比較字符串比比較數字要慢。

我的拿?停止使用比較信息更改節點。實際的比較模式在節點本身內無關。

然後,您只需編寫兩種比較方法,一種按成本與另一種按原產地進行比較。


並回到原來的問題,如何編寫比較器,考慮["a", "b", "aa"]排序?

你幾乎在那裏,但「長度」比較是不完整的。只有在長度不同的情況下,您才需要回到實際的詞彙比較中,因此您忘記了右側參數長度低於左側參數長度的情況。

因此,正確的方式是,假定兩個字符串:

bool compare(std::string const& lhs, std::string const& rhs) { 
    if (lhs.length() < rhs.length()) { return true; } 
    if (rhs.length() < lhs.length()) { return false; } // don't forget this 
    return lhs < rhs; 
} 
+0

謝謝!你的解決方案真的幫助我發現並理解問題是什麼並提醒我另一個我忘記的案例。 – BSchlinker 2011-04-26 10:09:25

0

你爲什麼不使用單一的比較和作出這樣的功能的小聰明?在開始時檢查數字字符,如果是這樣,請執行一對strtol()atoi()並比較結果。

否則根據您的非數字要求比較字符串的長度和字符。

+0

我想能夠排序字符串,類似於我如何排序數字。例如,叮咬「a」,「aa」和「b」應該被分類爲「a」,「b」,「aa」。我發佈的方法是我知道的唯一方法,可以讓我完成這個任務。 – BSchlinker 2011-04-26 05:52:18

+0

@BSchlinker:更新了我的答案。 – wallyk 2011-04-26 06:02:52

+0

不幸的是,這並不能解決我的問題。同樣的錯誤會發生=( – BSchlinker 2011-04-26 06:04:22

1

發現下面的代碼段拋出了錯誤,然後想到我的重載操作是如何工作的。

template<class _Ty1, class _Ty2> inline 
    bool _Debug_lt(_Ty1& _Left, _Ty2& _Right, 
     _Dbfile_t _File, _Dbline_t _Line) 
    { // test if _Left < _Right and operator< is strict weak ordering 
    if (!(_Left < _Right)) 
     return (false); 
    else if (_Right < _Left) 
     _DEBUG_ERROR2("invalid operator<", _File, _Line); 
    return (true); 
    } 

工作的解決方案是這樣的(再次修改這要感謝馬修M.留下評論)

// overloaded comparision operators 
friend bool operator<(const nodeRecord & record1, const nodeRecord & record2){ 
    // we need to deal with strings of different lengths... 
    if(record1.comparator.length() > record2.comparator.length() 
     && (record1.comparator.length() !=0 && record2.comparator.length() != 0)) 
     return false; 
    else if(record1.comparator.length() < record2.comparator.length() 
     && (record1.comparator.length() !=0 && record2.comparator.length() != 0)) 
     return true; 
    else 
     return (record1.comparator < record2.comparator); 
} 

謝謝大家誰幫助!