0

我创建了一个unordered_set我自己类型的struct. 我有一个iterator这个集合,想增加一个成员(count)指向的struct那个。iterator但是,编译器抱怨以下消息:

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;
} 

任何帮助是极大的赞赏!

4

3 回答 3

5

根据定义unordered_set, an中的元素是不可变的:

在 unordered_set 中,元素的值同时也是它的键,唯一地标识它。键是不可变的,因此,unordered_set 中的元素不能在容器中修改一次 - 但是可以插入和删除它们。

我会投票赞成您使用unordered_map代替,使用字符串作为键,使用 int 作为映射值。

于 2013-05-09T00:43:41.967 回答
2

一种解决方案(但一种肮脏的技巧)是使您的计数器可变,这意味着您允许即使在 const 对象上也可以更改它。

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

正如我已经说过的,这是一个肮脏的黑客,因为它允许你违反规则(你软化它们)。规则是有原因的。我什至不确定这是否有效,因为 的定义unordered_set说一旦插入就不能修改值,这也是有原因的。

一个更好的解决方案是使用一个使用单词作为键和计数器作为值的映射。然后,您的代码不必使用find,只需使用直接返回引用(而不是迭代器)的下标运算符(“数组访问”运算符)访问元素。在此参考上,使用增量运算符,如下所示:

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

那么你根本不需要你的结构,当然也不需要你的自定义比较运算符重载。


技巧(以防万一):如果您想按其值对地图进行排序(如果您需要一个最常用词排在第一位的统计地图),请使用具有反向键和值的第二个(但已排序)地图。这将按原始值对其进行排序,该值现在是键。以相反的顺序迭代它以从最常用的单词开始(或将其构造std::greater<int>为比较运算符,作为第三个模板参数提供)。

于 2013-05-09T00:45:42.310 回答
0

std::unordered_set 很不高兴,因为它担心您会以与另一个对象相同的方式更改对象,这会违反集合。ISTM 你真的想要一个从到的映射(根本不是一个集合),迭代器会让你改变返回的,如果不是键的话。stringint

于 2013-05-09T00:37:19.040 回答