2017-01-09 6 views
0

私はプログラミング割り当てのためにC++で接尾辞トライを実装しようとしています。今私は正しいアイデアを持っていると思うが、セグメンテーション・フォルトが発生し続けているため、その原因を見つけることができなかった。OOP/C++を使用して接尾辞トライを実装する

この割り当てでは、VIM /その他の基本的なテキストエディタを使用し、コンソールからプログラムをコンパイルすることをお勧めします。それにもかかわらず、私はエラーを見つけることができるように、コードを試してデバッグするためにCLionをダウンロードしました。

今すぐCLionで実行しているとき、私は、デバッガを実行しようとするとメッセージ

terminate called after throwing an instance of 'std::bad_alloc' 
    what(): std::bad_alloc 

を取得したメッセージに

Error during pretty printers setup: 
Undefined info command: "pretty-printer". Try "help info". 
Some features and performance optimizations will not be available. 

を与える私はCLionに新たなんだと私は何をすべきかわからないんだけどこれについて(私が使用する唯一のJetBrains IDEはPycharmです)。これを解決するのを手伝ってもらえますか?

このプログラム自体は、Trie,EdgeNodeという3つのクラスで構成されています。これらの実装は以下のとおりです。 Trieの実装の背後にある主な考え方は、Trie.cppのコンストラクタにあります。

コードの詳細は次のとおりです。私はどんな助けにも感謝します。


MAIN.CPP

#include <iostream> 
using namespace std; 

#include "Trie.hpp" 

int main(){ 

    string s = "Stef"; 
    Trie trie(s); 


    return 0; 
} 

Trie.hpp

#ifndef TRIE_HPP 
#define TRIE_HPP 

#include <string> 
#include "Node.hpp" 
#include "Edge.hpp" 
using namespace std; 

class Trie{ 

    private: 
     string T; 
     vector<Node> nodes; 
     void addWord(Node*, string); 

    public: 
     Trie(string);  

}; 

#endif 

Trie.cpp

#include <iostream> 
#include <cstring> 
#include "Trie.hpp" 
using namespace std; 

Trie::Trie(string T){ 
    T += "#";       //terminating character  
    this->T = T; 

    vector<string> suffix;    //array of suffixes 
    for(unsigned int i = 0; i < T.length(); i++) 
     suffix.push_back(T.substr(i, T.length()-i)); 

    //Create the Root, and start from it 
    nodes.push_back(Node(""));   //root has blank label 
    Node* currentNode = &nodes[0]; 

    //While there are words in the array of suffixes 
    while(!suffix.empty()){ 

     //If the character under consideration already has an edge, then this will be its index. Otherwise, it's -1. 
     int edgeIndex = currentNode->childLoc(suffix[0].at(0));  

     //If there is no such edge, add the rest of the word 
     if(edgeIndex == -1){ 
      addWord(currentNode, suffix[0]);    //add rest of word 
      suffix.erase(suffix.begin());     //erase the suffix from the suffix array 
      break;           //break from the for loop 
     } 

     //if there is 
     else{ 
      currentNode = (currentNode->getEdge(edgeIndex))->getTo();  //current Node is the next Node 
      suffix[0] = suffix[0].substr(1, suffix[0].length());      //remove first character 
     }   
    } 
} 

//This function adds the rest of a word 
void Trie::addWord(Node* parent, string word){ 
    for(unsigned int i = 0; i < word.length(); i++){    //For each remaining letter 
     nodes.push_back(Node(parent->getLabel()+word.at(i)));  //Add a node with label of parent + label of edge 
     Edge e(word.at(i), parent, &nodes.back());     //Create an edge joining the parent to the node we just added 
     parent->addEdge(e);           //Join the two with this edge 
    } 
} 

Node.hpp

#ifndef NODE_HPP 
#define NODE_HPP 

#include <string> 
#include <vector> 
#include "Edge.hpp" 
using namespace std; 

class Node{ 

    private: 
     string label;   
     vector<Edge> outgoing_edges; 

    public: 
     Node(); 
     Node(string); 
     string getLabel(); 
     int childLoc(char); 
     void addEdge(Edge); 
     Edge* getEdge(int); 
}; 

#endif 

Node.cpp

#include "Node.hpp" 
using namespace std; 

Node::Node(){ 
} 

Node::Node(string label){ 
    this->label = label; 
} 

string Node::getLabel(){ 
    return label; 
} 

//This function returns the edge matching the given label, returning -1 if there is no such edge. 
int Node::childLoc(char label){ 
    int loc = -1; 
    for(unsigned int i = 0; i < outgoing_edges.size(); i++) 
     if(outgoing_edges[i].getLabel() == label) 
      loc = i; 
    return loc; 
} 

void Node::addEdge(Edge e){ 
    outgoing_edges.push_back(e); 
} 

Edge* Node::getEdge(int n){ 
    return &outgoing_edges[n]; 
} 

Edge.hpp

#ifndef EDGE_HPP 
#define EDGE_HPP 

#include <string> 
using namespace std; 

class Node;   //Forward definition 

class Edge{ 

    private: 
     char label; 
     Node* from; 
     Node* to; 

    public: 
     Edge(char, Node*, Node*); 
     char getLabel(); 
     Node* getTo(); 
     Node* getFrom();  
}; 

#endif 

Edge.cpp

#include "Edge.hpp" 
using namespace std; 

Edge::Edge(char label, Node* from, Node* to){ 
    this->label = label; 
    this->from = from; 
    this->to = to; 
} 

char Edge::getLabel(){ 
    return label; 
} 

Node* Edge::getFrom(){ 
    return from; 
} 

Node* Edge::getTo(){ 
    return to; 
} 

答えて

0

&nodes[0];&nodes.back() - あなたは後で使用するためvectorへのポインタを格納している、とあなたがそれに要素を追加して、ベクターの基礎となるストレージが再配置されたときにこれらが無効になります。

あなたの好きなC++ブックで、一般的なポインタ、特に動的な割り当てについて読んでください。
お気に入りのC++ブックがまだない場合は、this listから1つを選択してください。

+0

返信いただきありがとうございます。私が理解しているかどうかわからない - あなたはそれが基礎ストレージが移転されたことを意味しますか?そして、 '&nodes [0]'ではなく 'nodes'の最初の要素を指すように' currentPointer'を設定するにはどうすればよいでしょうか? –

+0

@LukeCollinsベクトルは、その要素を動的に割り当てられた配列に格納します。要素を追加すると、この配列は移動および展開されます。 (これはまともな入門書でカバーされています。)2番目の質問に対する答えは、あなたがしてはならないことです。ノードを識別する別の方法を考え出すべきです。 (私はそのアドレスの代わりにノードのインデックスを使用します)。 – molbdnilo

関連する問題