2015-05-15 2 views
-1

Я знаю, что это длинный вопрос для моего первого вопроса, но я буквально пытался решить это в течение 2 недель безрезультатно.Ошибка сегментации (сбрасывание ядра) в реализации списка [C++]

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

Вот код:

#include <iostream> 
#include <fstream> 
#include <cstdlib> 
#include <cstring> 

using namespace std; 

typedef string tElemLista; 

typedef struct nodo { 
    tElemLista title; 
    tElemLista info; // el elemento en sí 
    nodo *next; // puntero autoreferencial 
    nodo *prev; 
    // al proximo nodo 
} tNodo; 

class tLista { 
    tNodo *head; 
    tNodo *tail; 
    tNodo *curr; 
    unsigned int listSize; 
    unsigned int pos; // posición actual en la lista 
public: 
    tLista() { 
     head = tail = curr = NULL; 
     listSize = 0; // lista vacía 
     pos = 0; 
    } 
    void Clear(){ 
     tNodo * temp; 
     moveToStart(); 
     while (listSize!=0){ 
      temp = curr; 
      moveToNext(); 
      free(temp); 
      listSize--; 
     } 

     head = tail = curr = (tNodo *)malloc(sizeof(tNodo)); 
     listSize = 0; // lista vacía 
     pos = 0; 

    } 
    int Insert(){ 
     tNodo * temp; 

     if (listSize == 0){ 
      head = tail = curr = (tNodo *)malloc(sizeof(tNodo)); 
      curr->next = curr->prev = NULL; 
      listSize++; 
     } 
     else if (curr == tail){ 
      curr->next = (tNodo *)malloc(sizeof(tNodo)); 
      curr->next->prev = curr; 
      if (curr == tail){ 
       tail = curr->next; 
      } 
      listSize++; 
     } 
     else{ 
      temp = curr->next; 
      curr->next = (tNodo *)malloc(sizeof(tNodo)); 
      curr->next->prev = curr; 
      curr->next->next = temp; 
      temp->prev = curr->next; 
      listSize++; 
     } 
     return pos; 
    } 
    int append(tElemLista item){ 
     unsigned int temp = pos; 
     moveToEnd(); 
     Insert(); 
     moveToPos(temp); 
     return pos; 
    } 
    tElemLista Remove(){ 
     tNodo * borrar; 
     tElemLista retorno = curr->info; 
     if (listSize == 1){ 
      free(curr); 
      head = tail = curr = NULL; 
      listSize = 0; 
     } 
     else if(curr == head){ 
      borrar = curr; 
      head = head->next; 
      if (head == NULL){ 
       tail = NULL; 
      } 
      else{ 
       curr = head; 
       head->prev = NULL; 
      } 
      listSize--; 
      free(borrar); 
     } 
     else if(curr == tail){ 
      borrar = curr; 
      tail = tail->prev; 
      if (tail == NULL){ 
       head = NULL; 
      } 
      else{ 
       curr = tail; 
       tail->next = NULL; 
      } 
      listSize--; 
      pos--; 
      free(borrar); 
     } 
     else{ 
      borrar = curr; 
      curr->prev->next = curr->next; 
      curr->next->prev = curr->prev; 
      listSize--; 
      free(borrar); 
     } 
     return retorno; 
    } 

    void moveToStart(){ 
     curr = head; 
     pos = 0; 
    } 
    void moveToEnd(){ 
     curr = tail; 
     pos = listSize; 
    } 
    void moveToNext(){ 
     if (curr != tail){ 
      //cout<< "\n\n" << curr->next<< "\n\n\n"; 
      curr = curr->next; 
      pos++; 
     } 
    } 
    void moveToPrev() { 
     if (curr != head){ 
      curr = curr->prev; 
      pos--; 
     } 
    } 

    int length(){ 
     return listSize; 
    } 
    int currPos(){ 
     return pos; 
    } 
    void moveToPos(unsigned int to){ 
     while (to != pos){ 
      if (to > pos){ 
       moveToNext(); 
      } 
      else{ 
       moveToPrev(); 
      } 
     } 
    } 
    tElemLista getValue(){ 
     return curr->info; 
    } 
    tElemLista setValue(tElemLista input){ 
     tElemLista antiguo; 
     //cout << input <<"\n"; 
     curr->info = input; 
     return antiguo; 
    } 
    tElemLista getTitle(){ 
     return curr->title; 
    } 
    tElemLista setTitle(tElemLista input){ 

     tElemLista antiguo; 

     //cout << curr->title <<"\n"; 
     //cout << input <<"\n"; 
     //cout << "OO"; 
     curr->title = input; 
     //cout << curr->title <<"\n"; 
     return antiguo; 
    } 

}; 


int main(){ 
    string linea_input; //El profesor Arroyuelo nos dijo que podíamos usar string de STL. 
    string comando; 
    string info; 
    string opened_output; 

    tLista Presentacion; 

    fstream archivo_input("input.txt"); 
    fstream archivo_output; 

    if (!archivo_input.is_open()){ 
     perror("Error al abrir input.txt"); 
     return 1; 
    } 

    while(!archivo_input.eof()){ 
     getline(archivo_input, linea_input); 

     size_t found; 
     if ((found = linea_input.find(" ")) != string::npos){ 
      comando = linea_input.substr(0,found); 
      info = linea_input.substr(found+1, string::npos); 

      if (comando == "NUEVA_PRESENTACION"){ 
       info.append(".txt"); 
       Presentacion.Insert(); 
       //cout << info; 
       opened_output = info; 
       archivo_output.open(opened_output.c_str()); //Crear archivo 
      } 
      else if (comando == "CARGAR_PRESENTACION"){ 

      } 

      else if (comando == "SET_CONTENIDO"){ 

       Presentacion.setValue(info); 
      } 
      else if (comando == "SET_TITULO"){ 
       //cout << "HM"; 
       Presentacion.setTitle(info); 
      } 




     } 
     else{ 
      if (linea_input == "NUEVA_DIAPOSITIVA"){ 

       Presentacion.Insert(); 
       //cout << "UNOVA\n"; 
      } 
      else if (linea_input == "VER_DIAPOSITIVA"){ 
       cout << "Posicion: " << Presentacion.currPos(); 
       cout << " - Titulo: " << Presentacion.getTitle(); 
       cout << " - Contenido: " << Presentacion.getValue() << "\n"; 
      } 
      else if (linea_input == "SIGUIENTE"){ 
       Presentacion.moveToNext(); 
      } 
      else if (linea_input == "ANTERIOR"){ 
       Presentacion.moveToPrev(); 
      } 
      else if (linea_input == "ELIMINAR_DIAPOSITIVA"){ 
       Presentacion.Remove(); 
      } 
      else if (linea_input == "GUARDAR"){ 
       unsigned int temp_pos = Presentacion.currPos(); 
       Presentacion.moveToStart(); 
       archivo_output << "DIAPOSITIVA #" << Presentacion.currPos() << "\n"; 

       archivo_output << Presentacion.getTitle() << "\n"; 
       archivo_output << Presentacion.getValue() << "\n"; 

       while(Presentacion.currPos() != Presentacion.length()- 1){ 

        Presentacion.moveToNext(); 
        archivo_output << "DIAPOSITIVA #" << Presentacion.currPos() << "\n"; 
        archivo_output << Presentacion.getTitle() << "\n"; 
        archivo_output << Presentacion.getValue() << "\n"; 
        archivo_input.close(); 
        archivo_input.open(opened_output.c_str()); 
       } 
       Presentacion.moveToPos(temp_pos); 
      } 
      else if (linea_input == "SALIR"){ 
       Presentacion.Clear(); 
       return 0; 
      } 
     } 
     /* 
     if(linea_input.npos != pos_corte) { 
      comando = comando.substr(pos_corte + 1); 
      linea_input = linea_input.substr(0, pos_corte); 
     } 
     */ 
     //cout << linea_input << "\n"; 
     //cout << comando << "\n"; 


     //cout << comando << "\n"; 
    } 

    archivo_input.close(); 
    return 0; 
} 

Любая помощь?

EDIT: Вот файл input.txt:

NUEVA_PRESENTACION TAAA 
SET_TITULO titulo 1 
SET_CONTENIDO blah blah blah 
SET_CONTENIDO blah 
VER_DIAPOSITIVA 
GUARDAR 
SALIR 
+0

При запуске этого кода в отладчике, на какой линии делает происходит выдаёт ошибку сегментации? –

+0

'и хотя я искал решения других людей, мне не повезло.« Вы теряете время, если вы так считаете, что решите свою проблему. Программирование не является математическим упражнением, где есть «решение», которое вы можете подключить (если вы не скопируете их функции и код). Вы должны отлаживать свой код, чтобы выяснить, что не так. Вероятность того, что кто-то закодировал точно такие же функции, с теми же строками кода, что и у вас, близок к 0. – PaulMcKenzie

+2

Кроме того, вы должны были протестировать этот класс перед выполнением любых операций ввода-вывода файлов. Вы открываете файл, и мы не знаем, какие данные вы использовали. Пожалуйста, разместите несколько строк выборочных данных, которые дублируют проблему. – PaulMcKenzie

ответ

5

Во-первых, вы должны написали очень небольшую тестовую программу перед заливая себя всякими файл ввода/вывода и других вещей, которые не важно.

Я взял свой код, и создал следующий 3 линии main программы (я использую Visual C++ 2013):

int main() 
{ 
    tLista myList; 
    myList.append("abc"); 
    myList.append("123"); // < -- hangs here 
} 

Это то, что вы должны начали с и испытаны.

Это все, что мне нужно, чтобы дублировать одну важную проблему с вашим кодом. Вопрос здесь:

head = tail = curr = (tNodo *)malloc(sizeof(tNodo)); 

Вы не использования malloc может создать tNodo объект. Этот класс содержит элемент std::string, что означает, что он не является типом POD.

Вы не можете создавать экземпляры не-POD с использованием malloc (если только вы не используете placement-new). Вы должны использовать new для динамического создания объекта.

head = tail = curr = new tNodo(); 

Вы делаете такую ​​же ошибку и в других частях кода.

Это только одна очевидная ошибка. У вас могут быть другие, поэтому я предлагаю вам отказаться от вашей программы main и написать простые тесты, как я сделал выше.

Более подробную информацию о типах POD: What are POD types in C++?

+0

Спасибо!Это решило это на данный момент. Сейчас я собираюсь сделать много тестов, чтобы проверить, есть ли другие. Наверное, мне нужно было проверить его больше, чем я. –

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