2017-01-09 3 views
3

Я реализую суффикс trie в C++. Реализация контура Trie приведена ниже.Доступ к первому символу строки без символов

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

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

    nodes.reserve(T.length() * (T.length() + 1)/2); //The number of nodes is bounded above by n(n+1)/2. The reserve prevents reallocation (http://stackoverflow.com/questions/41557421/vectors-and-pointers/41557463) 

    vector<string> suffix;    //vector 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 vector 
     } 

     //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 и Edge, которые имеют некоторые методы получения и установки свойств и можно было ожидать. Метод childLoc() возвращает местоположение ребра (если оно существует), представляющее заданный символ.

код компилируется нормально, но по какой-то причине, я получаю эту ошибку во время выполнения:

terminate called after throwing an instance of 'std::out_of_range' 
    what(): basic_string::at: __n (which is 0) >= this->size() (which is 0) 
Aborted (core dumped) 

Я сказал, что эта ошибка означает, что я доступ первый символ пустой строки, но я не вижу, где это происходит в коде.

+0

вы отлажена код с помощью отладчика? например скомпилировать с флагом '-g' с g ++, а затем использовать отладчик на основе gdb для выполнения кода ... –

+0

Очень сложно помочь вам с ошибкой времени выполнения, не имея возможности скомпилировать этот пример. Вы должны пройти через код с отладчиком на вашем конце. Если вы хотите получить ответ, вам нужно будет уменьшить пример и предоставить входные данные, которые создают вашу проблему. См. [Эту ссылку] (http://stackoverflow.com/help/mcve) о том, как создать полезный пример, который привлечет больше ответов. –

+0

Итак, где-то вы не путаете ни одной нитки колбас с нитью колбас. Легко сделать, так как и std:; строка не может быть нулевой, в отличие от C char *. –

ответ

0

Я вижу две части кода, которые потенциально несет ответственность за std::out_of_range:

Первое: Следующее выражение может получить доступ к пустой строке в позиции 0. Это может произойти (как показано во второй части), вы сжиматься строки, содержащиеся в suffix -вектором:

int edgeIndex = currentNode->childLoc(suffix[0].at(0)); 

Во-вторых, вы действуете на записи в suffix -вектором с риском, что строки в короткие :

suffix[0] = suffix[0].substr(1, suffix[0].length()); 

substr Операция также даст std::out_of_range, если первый операнд (т.е. pos -argument) превышает длину массива (см): string::substr

pos: Позиция первого символа, который будет скопирован как подстрока. Если соответствует длине строки, функция возвращает пустую строку . Если это больше длины строки, она выдает out_of_range. Примечание. Первый символ обозначается значением 0 (не 1).

Для выяснения, какие из этих выражений фактически отвечает за исключением, я хотел бы предложить, чтобы проконсультироваться с отладчиком :-)

+0

Что касается первого замечания, это не окончательная строка, вытолкнутая длиной 'T.length() - (T.length-1)' = 1? –

+0

@ Лук Коллинз: Да, вы правы. Я соответствующим образом адаптировал ответ. –

+0

@LukeCollins 'suffix [0] .substr (1, suffix [0] .length())' будет терпеть неудачу в строке с 1 символом, поскольку в индексе 1 нет символов.Это также ** будет терпеть неудачу для каждой строки, поскольку аргумент length является полной длиной строки, но вы начинаете с индекса 1 и, следовательно, переполняете строку на единицу. Если вы хотите, чтобы строка начиналась с символьного индекса, проще просто оставить аргумент длины. т.е.: 's.substr (1)' получает все после первого символа, предполагая, что строка имеет более одного символа для начала. – ebyrob

Смежные вопросы