在C ++中迭代地图时SIGSEGV信号

时间:2013-01-02 21:49:07

标签: c++ map iterator sigsegv

我试图解决这个问题大约5天而且没有运气,我试过的每个解决方案都失败了。

我发现了SIGSEGV的一些原因,但没有任何帮助 What is SIGSEGV run time error in C++?

好的,这是代码。 我有2个实例,其中包含一些关键字功能及其分数

我想获得他们的eucleidian距离,这意味着我必须为每个实例保存所有关键字,然后找到第一个关键字与第二个关键字的差异,然后找到其余的差异第二个例子。我想要的是在迭代第一个地图时,能够从第二个地图中删除元素。由于我们有两个消息集合,因此多次调用以下方法,并将来自第一个消息集合的每条消息与来自第二个消息集合的每条消息进行比较。

我有这个代码,但它突然停止了,虽然我检查它工作了几秒钟,我放在一些地方多个cout

请注意,这是针对大学的任务,所以我不能使用提升和所有这些技巧。但我想知道如何绕过我遇到的问题。

float KNNClassifier::distance(const Instance& inst1, const Instance& inst2) {   
map<string,unsigned> feat1;
map<string,unsigned> feat2;
for (unsigned i=0; i<inst1.getNumberOfFeatures(); i++) {
  feat1[inst1.getFeature(i)]=i;
}
for (unsigned i=0; i<inst2.getNumberOfFeatures(); i++) {
  feat2[inst2.getFeature(i)]=i;
}
float dist=0;

map<string,unsigned>::iterator it;
for (it=feat1.begin(); it!=feat1.end(); it++) {
  if (feat2.find(it->first)!=feat2.end()) {//if and only if it exists in inst2
    dist+=pow( (double) inst1.getScore(it->second) - inst2.getScore(feat2[it->first]) , 2.0);
    feat2.erase(it->first);
  }
  else {
    dist+=pow( (double) inst1.getScore(it->second) , 2.0);
  }
}

for (it=feat2.begin(); it!=feat2.end(); it++) {//for the remaining words
  dist+=pow( (double) inst2.getScore(it->second) , 2.0);
}
feat1.clear(); feat2.clear(); //ka8arizoume ta map gia thn epomenh xrhsh
return sqrt(dist);    
}

我也试过这个想法,以便不必删除某些内容,但它也会突然停止。

float KNNClassifier::distance(const Instance& inst1, const Instance& inst2) {
map<string,unsigned> feat1;
map<string,unsigned> feat2;
map<string,bool> exists;
for (unsigned i=0; i<inst1.getNumberOfFeatures(); i++) {
  feat1[inst1.getFeature(i)]=i;
}
for (unsigned i=0; i<inst2.getNumberOfFeatures(); i++) {
  feat2[inst2.getFeature(i)]=i;
  exists[inst2.getFeature(i)]=false;
  if (feat1.find(inst2.getFeature(i))!=feat1.end()) {
    exists[inst2.getFeature(i)]=true;
  }
}
float dist=0;
map<string,unsigned>::iterator it;
for (it=feat1.begin(); it!=feat1.end(); it++) {
  if (feat2.find(it->first)!=feat2.end()) {
    dist+=pow( (double) inst1.getScore(it->second) - inst2.getScore(feat2[it->first]) ,      2.0);
  }
  else {
    dist+=pow( (double) inst1.getScore(it->second) , 2.0);
  }
}

for (it=feat2.begin(); it!=feat2.end(); it++) {
  if(it->second==false){//if it is true, it means the diff was done in the previous iteration
    dist+=pow( (double) inst2.getScore(it->second) , 2.0);
  }
}

feat1.clear(); feat2.clear(); exists.clear();
return sqrt(dist);
}

1 个答案:

答案 0 :(得分:1)

代码本身似乎没问题(我以前发现的错误不是一个错误)。然而, 可能有一种更简单的方法:

  1. 不是从第二组中的第一组中查找字符串,而是可以同时在两个列表中移动并将迭代器推进到较小的元素或两个迭代器(如果它们使用相同的字符串)。在每种情况下都直接进行相应的计算。
  2. 我个人会使用两个已排序的std::vector<std::pair<std::string, unsigned int> >,但std::map<std::string, unsigned int>也适用。
  3. 我无权访问您的Instance课程,因此未对其进行测试,但以下内容应该有效。

    struct compare1st {
        bool operator()(std::pair<std::string, unsigned int> const& p1,
                        std::pair<std::string, unsigned int> const& p2) const {
            return p1.first < p2.first;
        }
    };
    
    std::vector<std::pair<std::string, unsigned int> > fill(Instance const& inst) {
        std::vector<std::pair<std::string, unsigned int> > rc;
        for (unsigned int i(0), end(inst.getNumberOfFeatures()); i != end; ++i) {
            rc.push_back(std::make_pair(inst.getFeature(i), i));
        }
        std::sort(rc.begin(), rc.end(), compare1st());
        return rc;
    }
    double square(double d) { // pow(d, 2.0) is fairly expensive
        return d * d;
    }
    
    float KNNClassifier::distance(const Instance& inst1, const Instance& inst2) {   
        typedef std::pair<std::string, unsigned int> Pair;
        std::vector<Pair> feat1 = fill(inst1);
        std::vector<Pair> feat2 = fill(inst2);
    
        std::vector<Pair>::const_iterator it1(feat1.begin()), end1(feat1.end());
        std::vector<Pair>::const_iterator it2(feat2.begin()), end2(feat2.end());
        double result(0.0);
        while (it1 != end1 && it2 != end2) {
            if (it1 != end1 && (it2 == end2 || it1->first < it2->first)) {
                result += square(inst1.getScore((it1++)->second);
            }
            else if (it2 != end2 && (it1 == end1 || it2->first < it1->first))
                result += square(inst2.getScore((it2++)->second);
            }
            else {
                result += square(inst1.getScore((it1++)->second)
                                 -  inst2.getScore((it2++)->second);
            }
        }
        return sqrt(result);
    }