Связанный список иногда загружает значения

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

#include <iostream>
#include <string.h>
#include <cstring>
#include "Nodo.h"
#include "Stack.h"
#include "Lista.h"

using namespace std;

void menu(){
  cout<<"1: Ingresar cliente "<<endl;
  cout<<"2: Eliminar cliente "<<endl;
  cout<<"3: Visualizar clientes "<<endl;
  cout<<"4: Salir "<<endl;
}

int main(){
  Lista <string> l;
  string name;
  int op,pos;

  do{
    menu();
    cin >> op;

    switch(op){

      case 1:

        cout<<"Ingrese Nombre\n";
        cin>>name;
        l.insertValue(name);
        break;     

      case 2:

        cout<<"Ingrese cliente a eliminar\n";
        cin>>pos;
        l.deleteAt(pos);
        break;   

      case 3:

        l.printList();
    }

    system("pause");      
    system("cls");  

  }while(op!=4);

  Lista <string> l1;
  return 0;
}

List.h

    #include "Nodo.h"
    #include <iostream>
    #ifndef  _LISTA_H
    #define  _LISTA_H

    using namespace std;

    template <class T> class Lista{

      protected:

        T dato;
        Nodo<T>* lista;

      public:

        Lista(){
          lista=0;
        }

        void deleteAt(int p){
          Nodo<T>* temp = lista;

          if(p==1){
            lista=lista->obtenerEnlace();
            free(temp);
          }
          else{
            for(int i =0;i<p-2;i++) temp=temp->obtenerEnlace();

            Nodo<T>* temp2 =temp->obtenerEnlace();
            temp->ponerEnlace(temp2->obtenerEnlace());
            free(temp2);
          }
        }

        void insertValue(T d){
          Nodo<T> * nuevo =(Nodo<T>*)malloc(sizeof(Nodo<T>));
          nuevo->ponerDato(d);
          nuevo->ponerEnlace(lista);
          lista=nuevo;
        }        

        void printList(){
          Nodo<T> * temp =lista;

          while(temp!=0){
            cout<<temp->obtenerDato()<<endl;
            temp=temp->obtenerEnlace();               
          }
        }
    };

    #endif

Узел.h

#ifndef _NODO_H 
#define _NODO_H


template <class T> class Nodo{

    protected:

    T dato;
    Nodo<T> * enlace;

    public:


    Nodo(T d){

        enlace=0;
        dato=d;

    }    


    Nodo(T d,Nodo * n){

        enlace=n;
        dato=d;

    }    


    Nodo<T>* obtenerEnlace() const{

        return enlace;     

    }


    void ponerEnlace(Nodo * n){

        enlace=n;   

    }

    void ponerDato(T d){

        dato=d;   

    }


    T obtenerDato() const{

        return dato;   

    }


};


#endif
0
задан 12.01.2017, 20:54
0 ответов
void deleteAt(int p){
  Nodo<T>* temp = lista;

  if(p==1){
    lista=lista->obtenerEnlace();
    free(temp);
  }
  else{
    for(int i =0;i<p-2;i++) temp=temp->obtenerEnlace();

    Nodo<T>* temp2 =temp->obtenerEnlace();
    temp->ponerEnlace(temp2->obtenerEnlace());
    free(temp2);
  }
}

Давайте предполагать, что нет элементов в списке... Что произойдет, если я позвоню в эту функцию? Он попробует соглашаться на не размещенную память и это не нравится... менее еще, если он кроме того пробует освобождать ее.

void deleteAt(int p){
  if( lista == 0 ) return;
  // ...
}

В C ++ индексы начинаются в 0. Что твоя функция отнеслась к первому элементу списка с индексом, 1 противоречащий общей норме и склонный к тому, чтобы давать ошибки. Правильное состояло бы в том, чтобы помещать:

if(p==0){
  lista=lista->obtenerEnlace();
  free(temp);
}

Вынуждать в тот, что первого индекса было 0, вынуждает тебя делать редкий алгоритм:

for(int i =0;i<p-2;i++) temp=temp->obtenerEnlace();

Не было бы более простым делать это?

while( p-- ) temp = temp->obtenerEnlace();

Хотя уже помещенные, чтобы предотвращать, что мы вытекли из списка:

while( p-- && temp ) temp = temp->obtenerEnlace();

Если мы анализируем другие возможные проблемы, мы можем обращать внимание в temp2

Nodo<T>* temp2 = temp->obtenerEnlace();

Что происходит если temp или temp2 укажи на 0? Легкий, приложение вновь расколется.

while( p-- && temp ) temp = temp->obtenerEnlace();

if( temp )
{
  Nodo<T>* temp2 = temp->obtenerEnlace();
  if( temp2 )
    temp->ponerEnlace(temp2->obtenerEnlace());

  free(temp2);
}

Которые являются многими проверками, но это цена, которая должна платить за то, чтобы работать с динамической памятью.

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


Это сбило со следа меня, потому что сначала приклеили этикетку на вопрос как C...

void insertValue(T d){
  Nodo<T> * nuevo =(Nodo<T>*)malloc(sizeof(Nodo<T>));
  nuevo->ponerDato(d);
  nuevo->ponerEnlace(lista);
  lista=nuevo;
}

В C ++ объекты нужно создавать их с new и удалять их с delete. malloc и free они служат для того, чтобы разместить или освободить память... Но они не назовут ни строителя, ни в разрушителя. Правильное состояло бы в том, чтобы делать:

void insertValue(T d){
  Nodo<T> * nuevo = New Nodo<T>(d);
  nuevo->ponerEnlace(lista);
  lista=nuevo;
}

И заменять это:

free(temp2);

Поэтому:

delete temp2;
1
ответ дан 03.12.2019, 17:44