2012-11-13 93 views
1

我有以下功能,無法弄清楚它爲什麼不起作用。爲什麼我的std :: set find()不起作用?

參數是一組非終結符和一個GrammarSymbol *(一個詞)的向量。非終結符是GrammarSymbol的一個子類。該函數應該過濾包含在單詞以及非終結集中的所有非終結符,並將它們返回到一個集合中。

std::set<Nonterminal> Filter(const std::set<Nonterminal>& symbolSet, const std::vector<GrammarSymbol*> w){ 

    //resulting set 
    std::set<Nonterminal> rSet; 

    std::vector<GrammarSymbol*>::const_iterator wit; 
    std::set<Nonterminal>::const_iterator ntit; 

    //iterate over all symbols of the word 
    for(wit = w.begin(); wit != w.end(); wit++){ 

    //test if current symbol is a nonterminal 
    const Nonterminal* nt = dynamic_cast<const Nonterminal*>(*wit); 
    if(nt != NULL){ 
     std::cout << "current symbol " << nt->Str() << " is nonterminal" << std::endl; 

     for(ntit = symbolSet.begin(); ntit != symbolSet.end(); ntit++){ 
     std::cout << ntit->Str() << " " << (!(*ntit < *nt) && !(*nt < *ntit))<< std::endl; 
     } 
     //look for the symbol in the nonterminal set 
     ntit = symbolSet.find(*nt); 

     //if the symbol was found, insert it into resulting set 
     if(ntit != symbolSet.end()){ 
     rSet.insert(*ntit); 
     std::cout << "inserted " << ntit->Str() << "into set, size: " << rSet.size() << std::endl; 
     } 
     else{ 
     std::cout << "not found in symbolSet" << std::endl; 
     } 
    } 
    } 
    return rSet; 
} 

這就產生輸出

current symbol (1, 2, 2) is nonterminal 
(1, 2, 2) 1 
(2, 3, 3) 0 
(3, 2) 0 
(4, 3) 0 
(5, 3, 1) 0 
not found in symbolSet 

如果我不依靠過濾功能,過濾器對我自己只是正常工作:

std::set<Nonterminal> Filter(const std::set<Nonterminal>& symbolSet, const std::vector<GrammarSymbol*> w){ 

    //resulting set 
    std::set<Nonterminal> rSet; 

    std::vector<GrammarSymbol*>::const_iterator wit; 
    std::set<Nonterminal>::const_iterator ntit; 

    //iterate over all symbols of the word 
    for(wit = w.begin(); wit != w.end(); wit++){ 

    //test if current symbol is a nonterminal 
    const Nonterminal* nt = dynamic_cast<const Nonterminal*>(*wit); 
    if(nt != NULL){ 
     std::cout << "current symbol " << nt->Str() << " is nonterminal" << std::endl; 

     for(ntit = symbolSet.begin(); ntit != symbolSet.end(); ntit++){ 
     std::cout << ntit->Str() << " " << (!(*ntit < *nt) && !(*nt < *ntit))<< std::endl; 
     if(!(*ntit < *nt) && !(*nt < *ntit)){ 
      rSet.insert(*ntit); 
     } 
     } 
    } 
    } 
    return rSet; 
} 

誰能給我解釋一下這裏發生了什麼?據我所知,std :: set應該將元素與運算符<進行比較。如輸出所示,比較似乎工作得很好。

我會繼續使用自制過濾器,但我擔心會有更大的潛在問題。

謝謝!

編輯:非終結和運營商<對非終結:

class Nonterminal : public GrammarSymbol{ 

    public: 

    /** The start state*/ 
    Idx mStartState; 
    /** The stack symbol*/ 
    Idx mOnStack; 
    /** The end state */ 
    Idx mEndState; 
    //... 
    } 

IDX僅僅是一個int的類型定義。

bool Nonterminal::operator<(const GrammarSymbol& other) const{ 
    if(typeid(*this) != typeid(other)) return true; //other is a terminal 
    const Nonterminal& nt = dynamic_cast<const Nonterminal&>(other); //other is a nonterminal 
    if (mStartState < nt.StartState()) return true; 
    if (mOnStack < nt.OnStack()) return true; 
    if (mEndState < nt.EndState()) return true; 
    return false;  
} 
+1

你可以顯示你的'Nonterminal :: operator <'做什麼? – Benj

+0

我已添加它。 – Shal

回答

3

operator <是不正確

考慮

Nonterminal nt1 (1,2,3); 
Nonterminal nt2 (3,2,1); 

bool b1 = nt1 < nt2; 
bool b2 = nt2 < nt1; 

nt1 < nt2比較:

  • 1 < 3 immediatelly yelds true;

對於nt2 < nt1

  • 3 < 1不成立,所以你繼續
  • 2 < 2這不成立,所以你繼續
  • 1 < 3持有

因此b1b2將是true,這完全是無稽之談

至於你的filter秒變種,它的工作原理becase的邏輯錯誤

for(ntit = symbolSet.begin(); ntit != symbolSet.end(); ntit++){ 
     std::cout << ntit->Str() << " " << (!(*ntit < *nt) && !(*nt < *ntit))<< std::endl; 
     if(!(*ntit < *nt) && !(*nt < *ntit)){ 
      rSet.insert(*ntit); 
     } 

這裏rSet.insert(*ntit);都會被調用一次if(!(*ntit < *nt) && !(*nt < *ntit))不成立,沒有一次因爲它應該。

+0

否。如果兩個非終結符比較,則只比較三個整數。 'if(typeid(* this)!= typeid(other))返回true;'只有當我比較非終結符和終端時纔會調用它(參見回答Benj的回答)。在你的例子中,因爲'1 <3'和'b2 = false',因爲'3!<1','b1 = true'會保持不變。 – Shal

+0

@Shal,對於'nt1 2012-11-13 12:26:19

+0

你說得對。道歉反駁它。 =)謝謝,我需要拿出一個更好的比較。 – Shal

相關問題