попытаться реализовать у меня двусвязный список;вызывая afficheList () дважды, я получаю бесконечный цикл? - PullRequest
0 голосов
/ 26 декабря 2018

вы хотели бы прочитать мой код и сказать мне, где я напортачил (я ожидаю, что afficheList (список списка) будет печатать элементы списка)?в самом праве моей реализации я пишу, как я понимаю мой код, и скажите мне, если я ошибаюсь, мне часто говорили, что есть разница между тем, что вы хотите, чтобы компьютер делал, и тем, что вы говорите, чтобы он делал, и мне интересно, стоит ли мне это делать "Попытка и ошибка ".Я боюсь утечки памяти!поскольку я использую динамическое выделение памяти

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

#include <iostream>

using namespace std;


/* dans ce fichier je tente de creer une structure d'une liste doublement chainé avec quelques methodes de base que j'y associe
tel que creer une liste, la supprimer, cree un element la suppremer, ajouter un element à la liste et afficher la liste.
les commentation aux dessus de chaque implementation sont les eventuels documentation quan dà  ceux sur les côtes ;  ma vision
de l'implemetation : ceux à  quoi je m'attends qu elle fasse !
*/




// je renome structure Element en elt
// ca me set dans la declaration des structures, elle m'eviter de reécrire  " struct Element" et aussis
//ca m'aide personnellement dans la comprehension des structures !
typedef struct Element elt;

//declaration de la structure Element
struct Element{
    int val;
    elt* next;                                          // pointeur vers l'element d'apres
    elt* prev;                                          //  - -    -   -    -    - d'avant
};

//declaration de la structure list
struct List{
    elt* first;                                         //un pointeur vers un elemnt qui
                                                        // qui saure  le premier element de
                                                        // de la liste
};
/**cree un element à partir d'un entier
*@param un entier
*@return un pointeur à un element
**/
elt* creeElement(int nb){
    Element *res= new Element;                           // j'allou  une memoire pouvant contenir un
                                                         // un element, j'y accede avec le pointer res
    res->val = nb;                                       // ds la memoire, ds la partie val j'y met le param nb
    res->next = nullptr;                                 // dans next je met null
    res->prev = nullptr;                                 // dans prev je met null
    return res;                                          // je retourne l'adress pointé par le pointeur *res
}
/* libere la memoire d'un pointeur  passe en param*/
void deleElement(Element *el){
    delete[] el;                                         // soit un pointeur *el,je libère l'addr mémo pointé
}
/**cree une liste
*@param un pointeur à un element
**/


List* creeList(Element *el){
    List *res = new List;
                                                       // vers un element (first)) je pointe cette mémo avec *res
    res->first = el;                                   // je fais pointé first vers l'adresse du pointeur *el
    return res;                                        // je retourne l'addr mémo du pointeur  *res;
}

/** affiche une liste
*@param un pointeur à une list
**/
void afficheList(List *l){

    Element *el = new Element;                        // pointeur *el pointe vers une mémo dispoé à contenir un elememnt
    el = l->first;                                    // je pointe à first par le pointeur *el
    cout << " {"<<el->val<<"} ";                      // j'affiche le champs val de *el
    while (el->next != nullptr){                      // tant que le pointeur *next de l'element actuel n'est pas null;
        el = el->next;                                // l'elemnt next devient l'element actuel ( par le pointeur el )
        cout << " {"<<el->val <<"} ";                 // j'affiche l'element actuel
    }
    cout << " {"<<el->next <<"} ";
    delete el;                                        // je libère le memoire occupé par le pointeur *el;
}
/** ajoute un element sur une liste
*@param un pointeur à un element et un ptr à une liste
*/
void ajouteElement(List *l, Element *el){
    Element *tempo = l->first;
    while (tempo->next != nullptr){
        tempo = tempo->next;
    }
    el->prev = tempo;
    tempo->next = el;
}

//debut d'echecs
void deleteList( List *l){
    Element *actuel=nullptr;
    Element *next=nullptr;
    actuel = l->first;

    //ca me fait une boucle infini :(
    while(actuel->next != nullptr){
        next = actuel->next;
        delete[] actuel;
        actuel = next;

    }

    delete[] next;

}

void pop_back_List(List *l){
    Element *cible;
    cible = l->first;
    while(cible->next != nullptr){
        cible = cible->next;
    }
    delete[] cible;
}



int main()
{
    cout << "Hello List!" << endl;
    Element *el = creeElement(10);
    List *l = creeList(el);
    ajouteElement(l, creeElement(-2));
    ajouteElement(l, creeElement(12));


    cout <<" list :  " ;
    afficheList(l);
    cout <<" list 1:  " ;
    afficheList(l);

    return 0;
}

я ожидалсписок: {10} {-2} {12}list1: {10} {-2} {12}вместо этого я получил бесконечный цикл: (

1 Ответ

0 голосов
/ 26 декабря 2018

Во-первых, C ++ не является Java или C # и т. Д.Запомни.Тем не менее, вы выделяете новый узел с этим кодом, а затем немедленно слите это распределение со следующей строкой:

Element *el = new Element; // el points to new node
el = l->first; // el points to head sentinal, node from above leaked

Затем вы используете el для перехода внизсвязанный список, в конечном итоге достигающий, как вы надеетесь, последний узел.Как только это происходит, вы прерываете цикл, но затем делаете это:

delete el; // delete last node in the list

На данный момент вы удалили узел из фактического списка. Первоначальное распределение, выполненное в первой строке, давно прошло(утечка), и теперь вы удалили узел из списка (последний узел), но указатель в списке , который ссылается на этот узел, все еще сохраняет исходный адрес (который теперь не существует;является висящим указателем ).

Повторное выполнение функции достигнет этого несуществующего висячего указателя, попытается следовать за ним и вызвать неопределенное поведение в процессе.

Две вещичтобы исправить это.Во-первых, эта функция не должна изменять список в первую очередь, поэтому не позволяйте этому.Будьте const правильными и передайте указатель List как const.Во-вторых, не выделяйте и не удаляйте память в этой функции вообще .

void afficheList(List const *l) {

    Element const *el = l->first;
    cout << " {" << el->val << "} ";
    while (el->next != nullptr) 
    {
        el = el->next;
        cout << " {" << el->val << "} ";
    }
    cout << " {" << el->next << "} ";
}

Вот и все.в этом коде все еще много других странных / неправильных вещей, но это самая большая проблема с afficheList

...