Liste => erste Versuche



  • Huh? Manchmal könntet Ihr Kerls Euch wirklich mehr Mühe beim formulieren geben...

    Also dafür echt mal ein ganz dickes ENTSCHULDIGUNG. Mir fällt das schon beim schreiben oft auf.... Manchmal wäre "echtes" unterhalten bedeutend einfacher.
    Naja, und es schießt oft schon ziemlich schnell aus mir raus, was nicht immer sooo überlegt ist

    Back to Topic:

    Wenn du in deinem Programm aber erst Speicher freigibst und danach noch auf diesen Speicher zugreifen willst, stimmt mit deiner Programmlogik etwas nicht.

    Ja, das ist mir mittlerweile klar. Aber...

    /* frees a complete list
       desc: frees all list elements and sets *l=NULL
       params: l pointer-to-pointer to a list
    */
    void clear_all(struct list **l);
    
    /* prints all list elements
       desc: prints all list elements. Does nothing if l is NULL.
       params: l pointer to a list or NULL
    */
    void show(struct list *l);
    

    ist mir jetzt noch nicht ganz klar. Ok clear_all bekommt dann einen Zeiger auf einen Zeiger der auf meine Liste zeigt... Dadurch könnte ich es so machen, das die Liste free wird, aber der "eine" Zeiger (Quasi der "Urzeiger" von *l der dann auch nicht mehr verkettet ist) speicherplatz behält , aber auf NULL zeigt??

    Hab ich das richtig verstanden?



  • beginner88888 schrieb:

    /* frees a complete list
       desc: frees all list elements and sets *l=NULL
       params: l pointer-to-pointer to a list
    */
    void clear_all(struct list **l);
    ...
    

    ist mir jetzt noch nicht ganz klar. Ok clear_all bekommt dann einen Zeiger auf einen Zeiger der auf meine Liste zeigt... Dadurch könnte ich es so machen, das die Liste free wird, aber der "eine" Zeiger (Quasi der "Urzeiger" von *l der dann auch nicht mehr verkettet ist) speicherplatz behält , aber auf NULL zeigt??

    Hab ich das richtig verstanden?

    Ich bin mir nicht sicher, was Du mit "Speicherplatz behält" meinst. Die Idee ist, der übergebene Zeiger wird auf NULL umgebogen.

    So wie Du es hier vorhast:

    beginner88888 schrieb:

    void clear_all(Liste *list){  
      Liste *tmp;
      while(list){
        tmp=list->next;
        free(list);
        puts("del");
        list=tmp;
      }
      list=NULL;   // <==neu
    }
    

    Wenn Du das so machst, kannst Du es auch gleich sein lassen - list ist ja eine Kopie des übergebenen Zeigers. Probier's aus.



  • void clear_all(Liste *list){  
      Liste *tmp;
      while(list){
        tmp=list->next;
        free(list);
        puts("del");
        list=tmp;
      }
      list=NULL;   // <=fällt unter Schnellschuß. Käse. 
    }
    

    Ja, das ist mittlerweile klar.

    Ich bin mir nicht sicher, was Du mit "Speicherplatz behält" meinst. Die Idee ist, der übergebene Zeiger wird auf NULL umgebogen.

    Ich glaub ich hab das so gemeint wie du es vorhattest, nur konnte ich es nicht richtig schreiben 🙂

    Mit *list hab ich nur eine Kopie des Zeigers, sprich ich kann die Liste Free machen, weil ich eine Kopie der Listenadressen hab, aber der Ursprüngliche Zeiger bleibt.

    Mit **list, mach ich mit dem Free das gleiche, setzte aber am Ende *list auf NULL.

    Also ich glaub das passt schon so. ABER...

    Die Idee ist, der übergebene Zeiger wird auf NULL umgebogen.

    nach clear_all(**list) ist *list=NULL.... Ich kann aber *list in show nur deswegen benuten, bzw. bekomme kein undefinertes verhalten, weil *list NICHT "gefreed" wurde sondern "nur" NULL zeigt ??



  • beginner88888 schrieb:

    Die Idee ist, der übergebene Zeiger wird auf NULL umgebogen.

    nach clear_all(**list) ist *list=NULL.... Ich kann aber *list in show nur deswegen benuten, bzw. bekomme kein undefinertes verhalten, weil *list NICHT "gefreed" wurde sondern "nur" NULL zeigt ??

    Nein, Du bekommst kein UB, weil Du nirgendwo einen NULL Zeiger oder einen Zeiger auf dem Du free() aufgerufen hast dereferenzierst.

    Der Ablauf wäre doch so:

    1. irgendwo in clear_all():
         free(*list); - klar der Speicherplatz der gesamten Liste muss freigegeben werden.
         *list = NULL;
    2. wenn show() jetzt souverän damit umgeht NULL als Argument zu bekommen -> kein Problem
    

    Trotzdem würde ich folgendes als schlechten Stil betrachten:

    Liste* l;
    // mit l arbeiten
    // ...
    clear_all(&l);
    show(l); // Logik?! Das ist einfach doof! ich habe l doch gerade gelöscht!
    

    Freigeben und auf NULL setzen sind zwei komplett unterschiedliche Dinge. Bei dieser Technik kommt nur beides zusammen.



  • wenn show() jetzt souverän damit umgeht NULL als Argument zu bekommen -> kein Problem

    Ist trotzdem doof, auch wenn´s kein Problem ist.
    Ich dachte ich bekomme UB schon allein deswegen, wenn ich einen Zeiger den ich gerade gefreed habe an eine Funktion übergebe, nicht erst wenn ich ihn dann in der Funktion dereferenziere...

    Nun gut, prinzipell hab ich's aber kapiert. Danke für die gute Erklärung, auch im anderen Thread...



  • So sieht jetzt die einfügen Version aus :

    Liste *einf_adv(Liste *list, Liste *insert, Liste *neu){    
          // *list =>Zeiger auf meine Liste ANFANG!! , *insert=>dahinter wird eingefügt, *neu =>daten des neuen Elements  RETURN : ZEiger auf Liste evtl. neuer ANFANG!!!!
    
    Liste *tmp, *anf;
    
    if (insert == list){            
               tmp=list;         
               list=neu;       
              // printf(" %c :: %d", list->cval, list->ival);
               list->next=tmp;   
               return list;     
               }
    
    anf=list;
    
    tmp=insert->next;   
    insert->next=neu;     
    neu->next=tmp;  
    
    return anf;
    
    }//END
    

    Ich denke das sollte so passen?? Glaub ich hab's jetzt "raus"... (Wenn das mal gut geht 😉 ... )



  • Wie fügst du ein neues Element hinter dem Ersten ein?
    Was ist, wenn die Liste leer (== NULL) ist?



  • Wie fügst du ein neues Element hinter dem Ersten ein?

    Also das funktioniert mit dem gepostetet Code. Hab das mehrmals probiert, an allen erdenklichen Stellen einzufügen , und auch eine neues "erstes" element einzufügen... Wo siehst du das Problem?

    Ja wenn die Liste leer ist, das hab ich vergessen. War vom einfügen und löschen geblendet 🙂



  • beginner88888 schrieb:

    Wo siehst du das Problem?

    Wenn insert != list ist, dann wird das Element hinter insert in die Liste eingefügt.
    Wenn insert == list ist, dann wird das Element vor insert in die List eingefügt.

    Also bekommst du nie ein Element hinter dem Ersten. Bzw. schon, weil das zweite Element vor dem Ersten eingefügt wird.

    Du hast eine Liste mit einem Element:
    List->[0]->NULL

    Jetzt fügst du ein mit einf_adv(List,[0],[1]) Dann hast du
    List->[1]->[0]->NULL
    Aber eigentlich sollte doch List->[0]->[1]->NULL raus kommen

    Jetzt fügst du ein mit einf_adv(List,[0],[2]) Dann hast du
    List->[1]->[0]->[2]->NULL

    Jetzt fügst du ein mit einf_adv(List,[1],[3]) Dann hast du
    List->[3]->[1]->[0]->[2]->NULL

    Nach alle dem hätte ich
    List->[0]->[2]->[1]->[3]->NULL
    erwartet.

    Etwas verworren. Das macht nicht das, was deine Kommentare angeben.



  • Oh... jetzt versteh ich . Hmm.. glaub so hab ich es nicht probiert.

    Ich hab erst die Funtkion nur fürs einfügen "hinter" insert geschrieben.
    Das hat einwandfrei geklappt, gehe auch davon aus das das passt.

    Dann ahb ich das zusammengebastelt das ich auch das "erste" Element ändern kann. Also am Listenanfang einfügen.
    Das hab ich wiederum getestet und hat auch funktioniert.
    Hinter dem ersten Element einfügen hab ich nur vor dieser Änderung probiert.

    Mist. Ok, das muss ich dann noch machen, genauso wie wenn die Liste leer ist.

    =>Wichtig für mich : Stimmt das vorgehen? Also ich war mir "fast" sicher das ich´s jetzt gecheckt hab....



  • Also vor Montag werd ich wohl nicht weitermachen, aber trotzdem ist mir noch was eingefallen :

    Unterscheiden ob Vor dem ersten Element oder Nach dem ersten Objekt eingefügt werden soll....
    =>Soll das meine Funktion machen, wenn ja evtl. über einen "Zusatzparameter"

    if (behind){
        ....
       }else....
    

    Oder soll das Vor dem ersten Element einfügen, generell eine andere Funktion erledigen....

    Oder ist alles Käse? Also ohne Zusatzparameter fällt mir jetzt auf Anhieb nix ein , wie ich erkennen soll "WO" es lang geht...



  • Ändere deinen Vergleich in

    if (insert == NULL){ // einfügen am Anfang der Liste
    

    dann passt das schon.

    Davor muss dann noch die Abfrage für

    if (list== NULL){ // Liste noch leer
    

    und natürlich die Behandlung davon.



  • Ändere deinen Vergleich in

    if (insert == NULL){ // einfügen am Anfang der Liste
    

    dann passt das schon.

    =>Wo war der Smiliy mit dem Brett und dem Tisch gleich nochmal??....
    Danke!!!



  • beginner_offl schrieb:

    =>Wo war der Smiliy mit dem Brett und dem Tisch gleich nochmal??....

    Was kann denn der Smiley dafür ?
    Es ist doch dein Brett. 🤡



  • nö, der Smily flüstert mir immer den Code ins Ohr 😃



  • Würdet ihr das "Listen-Thema" weiterführen oder.... Also die meisten Bücher enden mit Einfach-Verkettete-Liste... Das es da noch mehr gibt ist mir bekannt, aber da wären wir wieder bei der Frage die ich schon mal gestellt habe in dem Thread :

    beginner_of schrieb:

    =>Das verkettete Listen in der Praxis nicht wirklich oft vorkommen wurde schon besprochen... Weiterhin wäre aber noch interssant.. Baumstrukturen usw usw... Nice to know oder essential element??

    ...mir viel das bei dynamsichen Speicherreservierungen schon auf, das ich das für meine "pillepalle" Prog´s wohl nie wirklich sinnvoll nutzen werde, höchstens um in Übung zu bleiben, da ich fast immer weiß wieviel Speiche ich brauche, oder den Puffer groß genug mache. Aber da geht´s ja auch um nix 🙂

    Muss man mal gemacht haben oder... soll man mal gehört haben... oder braucht man wirklich öfters....

    Ich hoffe ihr wisst was ich meine ...


  • Mod

    Eine Baumstruktur sollte man mal programmiert haben, finde ich. Falls es das war, was du mit deinem Beitrag erfragen wolltest 😕 .

    Abgesehen davon, dass ich in meinen Programmen andauernd Baumstrukturen selber benutze, habe ich sogar mal notwendigerweise eine eigene, neue Baumstruktur entwickelt, weil ich mal ganz spezielle Ansprüche hatte. Da war es sicher auch nützlich, mit den einfachen Versionen Erfahrung zu haben.



  • Falls es das war, was du mit deinem Beitrag erfragen wolltest

    Durchaus. Wie gesagt, ich kann nicht wirklich einschätzen was man mal gemacht haben sollte, oder wo es reicht mel gehört zu haben....
    =>Darum die Frage an die Profis 🙂


  • Mod

    P.S. zu meinem Beitrag oben: Es ist auch gut, mal eine Listenstruktur programmiert zu haben. Wollte ich nur mal klar stellen, damit das keiner falsch liest. Ist eine gute Vorbereitung für die anderen, komplexeren Strukturen.



  • Ok. In das Thema der "Binären" Bäume werd ich mich aber diesmal erst gründlich einlesen. Will Eure Nerven nicht überstrapazieren :-).
    Ich denke aber es wird bestimmt die ein oder andere Frage auftauchen.

    @SeppJ : Ich weiß, keiner gibt gerne was von seinen "Schätzchen" Preis, aber vielleicht als kleine Info für die wissbegierigen....

    dass ich in meinen Programmen andauernd Baumstrukturen selber benutze

    ...Was , oder wofür brauchst du die so oft?

    Nicht falsch verstehen, aber es viel mir bei LIsten schon etwas schwer den Anwendungsfall zu erkenne, da das Beispiel mit dem Telefonbuch und Automarke+Farbe.... aus den meisten Büchern.... Naja...etwas mau ist. Gut, meine Liste reiht sich mühelos ein in die Liste der Sinnlosen Programme...


Anmelden zum Antworten