在while循环和segfault C ++中使用erase()

时间:2015-02-09 22:20:26

标签: c++ string parsing getline

好的,所以我在这里遇到了一些问题。问题是这个代码在朋友的计算机上运行,​​但是当我尝试运行它时,我遇到了分段错误。

我正在阅读一个看起来像这样的文件:

word 2 wor ord
anotherword 7 ano oth the her erw wor ord
...

我想解析文件的每个字。前两个单词(例如word和2)将被删除,但在过程中将第一个单词保存在另一个变量中。

我已经看了一下实现这一点,并且我已经想出了这部半码的代码,似乎可以在我朋友的电脑上运行,但不是我的。

Dictionary::Dictionary() {
    ifstream ip;
    ip.open("words.txt", ifstream::in);
    string input;
    string buf;
    vector<string> tokens; // Holds words
    while(getline(ip, input)){
        if(input != " ") {
            stringstream ss(input);
            while(ss >> buf) {
                tokens.push_back(buf);
        }
        string werd = tokens.at(0);
        tokens.erase(tokens.begin()); // Remove the word from the vector
        tokens.erase(tokens.begin()); // Remove the number indicating trigrams
        Word curr(werd, tokens); 
        words[werd.length()].push_back(curr); // Put the word at the vector with word length i.
        tokens.clear();
    }
}
ip.close();
}

在文件中解析这种结构并删除前两个元素但保存其他元素最好的是什么?正如您所看到的,我正在创建一个包含字符串和向量的Word对象供以后使用。

此致

EDIT;它似乎添加第一行很好,但在删除第二个元素时,它会因分段错误错误而崩溃。

EDIT; words.txt包含:

addict 4 add ddi dic ict 
sinister 6 ini ist nis sin ste ter 
test 2 est tes 
cplusplus 7 cpl lus lus plu plu spl usp 

不带空格或结尾空格。并不是说它一直都是读。

Word.cc:

#include <string>
#include <vector>
#include <algorithm>
#include "word.h"

using namespace std;

Word::Word(const string& w, const vector<string>& t) : word(w), trigrams(t) {}

string Word::get_word() const {
    return word;
}

unsigned int Word::get_matches(const vector<string>& t) const {
    vector<string> sharedTrigrams;
    set_intersection(t.begin(),t.end(), trigrams.begin(), trigrams.end(), back_inserter(sharedTrigrams));
    return sharedTrigrams.size();
}

3 个答案:

答案 0 :(得分:1)

首先,您发布的代码中关闭}的数量存在错误。如果你正确地缩进它们,你会看到你的代码是:

while(getline(ip, input))
{
   if(input != " ") 
   {
      stringstream ss(input);
      while(ss >> buf) {
         tokens.push_back(buf);
      }
   }
   string werd = tokens.at(0);
   tokens.erase(tokens.begin());
   tokens.erase(tokens.begin());
   Word curr(werd, tokens); 
   words[werd.length()].push_back(curr);
   tokens.clear();
}
}

假设这是一个很小的错误发布,另一个问题是tokensinput == " "时是一个空列表但你继续使用tokens,好像它有2个或更多项目在它。

您可以通过移动if语句中的所有内容来解决此问题。

while(getline(ip, input))
{
   if(input != " ") 
   {
      stringstream ss(input);
      while(ss >> buf) {
         tokens.push_back(buf);
      }

      string werd = tokens.at(0);
      tokens.erase(tokens.begin());
      tokens.erase(tokens.begin());
      Word curr(werd, tokens); 
      words[werd.length()].push_back(curr);
      tokens.clear();
   }
}

我会添加进一步的检查以使其更强大。

while(getline(ip, input))
{
   if(input != " ") 
   {
      stringstream ss(input);
      while(ss >> buf) {
         tokens.push_back(buf);
      }

      string werd;

      if ( !tokens.empty() )
      {
         werd = tokens.at(0);
         tokens.erase(tokens.begin());
      }

      if ( !tokens.empty() )
      {
         tokens.erase(tokens.begin());
      }

      Word curr(werd, tokens); 
      words[werd.length()].push_back(curr);
      tokens.clear();
   }
}

答案 1 :(得分:0)

你忘了包含变量的初始化&#34;单词&#34;在你的代码中。只是看着它,我猜你正在初始化&#34;单词&#34;是一个固定长度的向量数组,但然后读取一个不在数组末尾的单词。砰,你死了。添加一个支票给&#34; werd.length()&#34;确保它严格小于&#34;字&#34;

的长度

答案 2 :(得分:0)

ifstream ip;
ip.open("words.txt", ifstream::in);
string input;
while(getline(ip, input)){
   istringstream iss(input);
   string str;
   unsigned int count = 0;
   if(iss >> str >> count) {
     vector<string> tokens { istream_iterator<string>(iss),    istream_iterator<string>() }; // Holds words
  if(tokens.size() == count) 
        words[str.length()].emplace_back(str, tokens);
  }      
}
ip.close();

这是我过去的工作原理。