2014-09-26 94 views
2

我試圖創建一個從他們的長度排列文件中讀取的單詞列表。爲此,我試圖用自定義比較器來使用std :: set。使用自定義比較器與std ::設置

class Longer { 
public: 
    bool operator() (const string& a, const string& b) 
    { return a.size() > b.size();} 
}; 

set<string, Longer> make_dictionary (const string& ifile){ 
    // produces a map of words in 'ifile' sorted by their length 

    ifstream ifs {ifile}; 
    if (!ifs) throw runtime_error ("couldn't open file for reading"); 

    string word; 
    set<string, Longer> words; 

    while (ifs >> word){ 
    strip(word); 
    tolower(word); 
    words.insert(word); 
} 

remove_plurals(words); 

if (ifs.eof()){  
    return words; 
    } 
    else 
    throw runtime_error ("input failed"); 
} 

從這裏,我期望一個文件中的所有單詞按其長度排列的列表。相反,我得到一個非常短名單,可以精確到一個字的輸入上出現的每一個長度:

polynomially-decidable 
complexity-theoretic 
linearly-decidable 
lexicographically 
alternating-time 
finite-variable 
newenvironment 
documentclass 
binoppenalty 
investigate 
usepackage 
corollary 
latexsym 
article 
remark 
logic 
12pt 
box 
on 
a 

怎麼在這裏上的任何想法?

+0

請發表你的程序的只有*有關*一部分作爲[MCVE(http://stackoverflow.com/help/mcve)。 – Csq 2014-09-26 08:57:28

回答

3

使用您的比較器,等長字是相同的,並且您不能在一組中具有重複的等效項。

要保留多個單詞,您應該修改比較器,以便它在比較長度相同時也執行比較,如字典比較。

0

您的比較器只會按長度進行比較,這意味着尺寸相同但不同的字符串被視爲相當於std::set。 (std::set對待他們同樣如果沒有a < b也不b < a是真實的,與<作爲您的自定義比較器功能。)

這意味着你的比較還應該考慮字符串的內容,以避免這種情況。此處的關鍵字是lexicographic比較,這意味着您在帳戶中採用多個比較條件。第一個標準是你的字符串長度,第二個標準是字符串本身。編寫字典對比的簡單方法是利用std::tuple,它提供了一個比較運算符,通過重載operator<來對組件進行字典對比。

爲了讓你的「反向」長的順序,你有operator>寫道,與通常使用的operator<兼容,簡單地採取串的大小爲負,即第一重寫a.size() > b.size()-a.size() < -b.size(),然後以字符串組成它本身爲元組,最後用<比較的元組:

class Longer { 
public: 
    bool operator() (const string& a, const string& b) 
    { 
     return std::make_tuple(-a.size(), a) 
      < std::make_tuple(-b.size(), b); 
     //      ^^^^^^^^^ ^^^ 
     //      first second 
     //     criterion criterion 
    } 
};