【问题标题】:Using erase() in a while loop and segfault C++在while循环和段错误C++中使用erase()
【发布时间】:2015-04-09 19:52:57
【问题描述】:

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

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

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 对象,其中包含一个字符串和一个向量供以后使用。

问候

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

编辑; 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();
}

【问题讨论】:

  • 从文件开头读取一个空行很容易弄乱程序。与其将很多东西推到一个向量上然后删除其中两个,我建议一开始就不要推它们。
  • @chris 你又来了,尝试用简单的方法做事=P(uptick)
  • 单词数组的类型/大小?
  • The thing is this code works on a friend's computer but I'm getting segmentation faults when I try to run it. 好吧,问题不在于您的计算机。欢迎来到“未定义行为”的世界。
  • @PaulMcKenzie,谢天谢地,你在电脑商店的收银台上发现了我。

标签: c++ string parsing getline


【解决方案1】:

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

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

假设这是发布时的一个小错字,另一个问题是tokens 是一个空列表,而input == " " 但您继续使用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();
   }
}

【讨论】:

  • 抱歉,我在此处粘贴代码并出于我自己的错误检查目的删除了一个打印语句时错过了最后一个大括号。它不在真实的代码中。即使大括号正确,代码仍然不起作用。我尝试添加一个 vector exportTokens = vector(tokens.begin()+2, tokens.end());并删除 erase() 调用但仍然失败..
  • 由于您发布的代码没有MCVE,因此很难看出您的程序中可能存在哪些其他问题。
【解决方案2】:

您忘记在代码中包含变量“words”的初始化。只是看着它,我猜你正在将“单词”初始化为一个固定长度的向量数组,然后读取一个不在数组末尾的单词。砰,你死定了。为“werd.length()”添加一个检查,以确保它严格小于“words”的长度。

【讨论】:

  • 你是对的,但是 words 数组是 25 个插槽,我的文件中没有一个词这么大。
  • @enrm - and none of the words are this big in my file. 如果我为所有声称“我在做 x”但实际上没有做“x”的海报拥有一美元,我会成为一个有钱人。请确保通过编写代码来检查这种情况,数组没有被大字破坏。
【解决方案3】:
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();

这是我用来让它工作的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    相关资源
    最近更新 更多