2013-05-09 79 views
0

我創建了自己的struct類型的unordered_set。我有一個iterator這個集合,並且想要增加iterator指向的struct的成員(count)。然而,編譯器會抱怨以下消息:如何使只讀對象的迭代器可寫(使用C++)

main.cpp:61:18: error: increment of member ‘SentimentWord::count’ in read-only object

我該如何解決這個問題?

這裏是我的代碼:

#include <fstream> 
#include <iostream> 
#include <cstdlib> 
#include <string> 
#include <unordered_set> 


using namespace std; 


struct SentimentWord { 
    string word; 
    int count; 
}; 


//hash function and equality definition - needed to used unordered_set with type SentimentWord 
struct SentimentWordHash { 
    size_t operator() (const SentimentWord &sw) const; 
}; 

bool operator == (SentimentWord const &lhs, SentimentWord const &rhs); 



int main(int argc, char **argv){ 


    ifstream fin; 
    int totalWords = 0; 
    unordered_set<SentimentWord, SentimentWordHash> positiveWords; 
    unordered_set<SentimentWord, SentimentWordHash> negativeWords; 


    //needed for reading in sentiment words 
    string line; 
    SentimentWord temp; 
    temp.count = 0; 


    fin.open("positive_words.txt"); 
    while(!fin.eof()){ 
    getline(fin, line); 
    temp.word = line; 
    positiveWords.insert(temp); 
    } 
    fin.close(); 


    //needed for reading in input file 
    unordered_set<SentimentWord, SentimentWordHash>::iterator iter; 


    fin.open("041.html"); 
    while(!fin.eof()){ 
    totalWords++; 
    fin >> line; 
    temp.word = line; 
    iter = positiveWords.find(temp); 
    if(iter != positiveWords.end()){ 
     iter->count++; 
    } 
    } 


    for(iter = positiveWords.begin(); iter != positiveWords.end(); ++iter){ 
    if(iter->count != 0){ 
     cout << iter->word << endl; 
    } 
    } 


    return 0; 

} 


size_t SentimentWordHash::operator() (const SentimentWord &sw) const { 
    return hash<string>()(sw.word); 
} 


bool operator == (SentimentWord const &lhs, SentimentWord const &rhs){ 
    if(lhs.word.compare(rhs.word) == 0){ 
    return true; 
    } 
    return false; 
} 

任何幫助,不勝感激!

+0

[你可以通過不使用std :: set來解決這個問題](ftp://24.151.202.80/AiDisk_a1/Full/Completed/pdf/col1.pdf) – 2013-05-09 00:29:15

+0

[另一個帶'eof' bug的代碼?](http://stackoverflow.com/questions/2251433/checking-for-eof-in-stringgetline)(在while-condition中使用getline代替...) – leemes 2013-05-09 00:59:43

回答

4

元素是,by definition,不可改變:

在一個unordered_set,元件的值是在同一時間它的 鍵,標識它唯一地。密鑰是不可變的,因此,一個unordered_set中的 元素不能在容器中修改一次 - 但可以插入和刪除它們。

我會投票決定使用unordered_map,而不是使用字符串作爲鍵和int作爲映射值。

0

std :: unordered_set是不滿意的,因爲它擔心你會改變對象的方式與另一個對象相同,這將違反該設置。 ISTM你真的想要一個mapstringint(不是一個集合),並且迭代器會讓你改變返回的,如果不是關鍵。在unordered_set

2

一個解決方案(但骯髒的黑客)是讓你的計數器可變,這意味着你可以改變它,即使在const對象。

struct SentimentWord { 
    string word; 
    mutable int count; 
}; 

正如我已經說過了,這是一個骯髒的黑客,因爲它可以讓你違反規則(你軟化他們)。規則有一個原因。我甚至沒有肯定如果這個工程,因爲unordered_set的定義說,值插入後不能修改,這也有一個原因。

更好的解決方案是使用地圖,該地圖使用該字作爲關鍵字並將計數器作爲值。然後,您的代碼不必使用find,而只需使用直接返回引用(不是迭代器)的下標運算符(「數組訪問」運算符)訪問該元素。在此參考,使用增量運算符,就像這樣:

std::unordered_map<std::string,int> positiveWords; 
//... 
positiveWords[word]++; 

那麼你不需要你的結構可言,當然也沒有你的自定義比較運算符重載。


絕招(以防萬一你需要它):如果您想訂購一張地圖由它的價值(如果你需要與未來第一最頻繁的詞的統計圖),使用第二個(但訂購)映射與反轉的鍵和值。這將按原始值進行排序,這是現在的關鍵。按照相反的順序對其進行迭代,以最頻繁的詞開始(或者使用作爲比較運算符的std::greater<int>構造它,作爲第三個模板參數提供)。