2013-05-09 75 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>构造它,作为第三个模板参数提供)。