1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

einfach Liste mit struct - Einfügen und Ausgeben von Elementen

Dieses Thema im Forum "C/C++" wurde erstellt von neuesich, 16. April 2012.

  1. neuesich

    neuesich Grünschnabel

    Code (Text):
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3.  
    4. typedef struct list_izahl_element  {
    5.         int  izahl;
    6.         struct list_izahl_element *pnext;
    7.     } Liste_izahlen;
    8.  
    9. void print_list(Liste_izahlen **list){
    10.     int counter=1;
    11.     Liste_izahlen* runner=*list;
    12.  
    13.     if (!runner)
    14.         printf("Leere Liste!\n");
    15.     else
    16.         while (runner){
    17.             printf("%d. %d\n", counter++, runner->izahl);
    18.             runner=runner->pnext;}
    19. }
    20.  
    21. void insert(Liste_izahlen **select, int iZahlinput){
    22.     Liste_izahlen *newelement=(Liste_izahlen*) malloc (sizeof(Liste_izahlen));
    23.     newelement->izahl=iZahlinput;
    24.     newelement->pnext=NULL;
    25.  
    26.     if (*select==NULL)
    27.         *select=newelement;
    28.     else{
    29.         newelement->pnext=(*select)->pnext;
    30.         (*select)->pnext=newelement;}
    31.     free(newelement);
    32. }
    33.  
    34.  void insert_sort(Liste_izahlen **list, int iZahlinput){
    35.     Liste_izahlen *runner=*list;
    36.  
    37.     if (runner!=NULL)
    38.        while((iZahlinput>(runner->izahl))&&(runner->pnext!=NULL)&&(iZahlinput>(runner->pnext->izahl)))
    39.            runner=runner->pnext;
    40.     insert(&runner,iZahlinput);
    41. }
    42.  
    43. int main(void){
    44. int input=0;
    45. Liste_izahlen *xylist=NULL;
    46.  
    47. while(1){
    48.     printf("Geben Sie eine Ganzzahl ein: ");
    49.     if (scanf("%d", &input)){
    50.         insert_sort(&xylist,input);
    51.         print_list(&xylist);
    52.     }
    53. }
    54. }
    55.  
    Hallo,

    Ich stehe momentan total aufm Schlauch und komme nicht voran. Ich habe Probleme beim Erstellen und Einfügen einer Liste. Irgendwie passt die Zuordnung innerhalb der Funktion nicht. Ich bin dankbar für jede Hilfe!
    Lg
  2. ibafluss

    ibafluss Erfahrenes Mitglied

    Ich habe das Programm jetzt nicht ganz genau durchgeschaut, aber 2 Sachen einmal vorweg:

    1: Du übergibst an die Funktionen immer einen Pointer auf einen Pointer, das ist aber unnötigt, eine Dimension, also nur ein Pointer reicht vollkommen. So machst du deinen Code nur unübersichtlich.

    2: Beim 1.Durchlauf ist das if in Zeile 26 war und *select = newelement; wird gemacht. Danach in Zeile 31 schreibst du free (newlement), du gibst also das frei, auf was *select gerade zeigt, das ist keine gute Idee.

    Lg
  3. neuesich

    neuesich Grünschnabel

    Hey danke für die schnelle Antwort!

    zu 1. Ich habe mich an diesem Post aus dem Forum orientiert:

    Ich hab mich jetzt für zweiten Methode entschieden, oder ist die unpraktikabel? Der Vorteil ist/war, dass ich auch eine leere Liste übergeben kann und bei Methode 3 muss man ein erstes Element mit Nullwerten vorher initialisieren. Das fand ich auch unpraktikabel.

    zu 2. Ja stimmt, damit habe ich mir selbst ins Bein geschossen. Wenn ich die Zeile entferne, dann läuft die printf- und sort-Funktion schonmal wie sie sollte. Jetzt muss nur noch der Fehler in der insert_sort gefunden werden...
  4. sheel

    sheel Mod # I love Asm Moderator

    Hi

    Das mit dem Doppelpointer ist nur dann nötig,
    wenn die Liste (genauer das erste Element) in der Funktion verändert wird.
    Bei zB. print_liste würde auch ein einfacher Pointer reichen.

    Methode 3 ist auch ohne Element möglich.
    Man braucht nur eine Referenz auf den Pointer, nicht auf einen existierenden Inhalt.
    xylist im main reicht,auch wenn es NULL ist.

    Vorteil: Etwas weniger Schreibarbeit, und beim Aufruf muss man in keinem Fall ein & verwenden
    (egal ob Änderfunktion oder nicht)

    Nachteil: Wenn man reines C (ohne C++) programmieren will,
    darf man keine Referenzen verwenden. Die gibts in C nämlich nicht.


    Zum insert_sort und insert:
    insert selbst hat zuerst auch noch ein Problem:
    Es fügt immer nach dem aktuellen Element ein.
    Für insert_sort müsste es auch davor einfügen können.
    Weil sonst kann man bei einer bestehenden Liste nie am Anfang einfügen.


    Gruß

    PS: Nachträglich Willkommen bei tutorials.de :)
  5. ibafluss

    ibafluss Erfahrenes Mitglied

    Du kannst es auch mit Pointer auf Pointer machen, tut mir leid ich hatte einen kleinen Denkfehler.
    Das Problem ist hier, in Zeile 35 in insert_sort() zeigt der Zeiger runner auf das, was in xylist in der main() steht, also auf NULL. runner hat also nur mehr die Adresse NULL gespeichert und von xylist keine Adresse mehr, deshalb kannst du xylist nicht mehr abändern. Du arbeitest nur mehr mit runner weiter und hast keinen Bezugspunkt zu xylist.

    Du müsstest runner auch einen Pointer auf einen Pointer machen und da das speichern, auf was list zeigt, also so:

    Code (C++):
    1. Liste_izahlen **runner = list;
    Jetzt zeigt runner auf das, was list zeigt, also auf die Adresse von xylist vom main(). Ich hoffe ich habe das halbwegs verständlich ausgedrückt.

    Lg
  6. neuesich

    neuesich Grünschnabel

    Ok super, das klingt einleuchtend. Ich hab es mal im Code angepasst. Danke!

    Ja das habe ich mir auch überlegt. Ich habe die print_list nochmal angepasst.

    Ok dann scheidet Methode 3 sowieso aus, da es C sein soll.

    Fange ich das nicht ab durch
    Code (Text):
    1.  if (!*select)
    ? Dass die Funktion insert immer hinter ein übergebenes Element der Liste einträgt ist gewollt (und muss leider auch so sein). Ich dachte ich hätte den Sonderfall, dass die Liste leer ist durch die If-Bedingung abgedeckt (in insert_sort sowie auch in insert).

    Derzeit sieht es so aus:
    Code (Text):
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3.  
    4. typedef struct list_izahl_element  {
    5.         int  izahl;
    6.         struct list_izahl_element *pnext;
    7.     } Liste_izahlen;
    8.  
    9. void print_list(Liste_izahlen *list){
    10.     int counter=1;
    11.     Liste_izahlen* runner=list;
    12.  
    13.     if (!runner)
    14.         printf("Leere Liste!\n");
    15.     else
    16.         while (runner){
    17.             printf("%d. %d\n", counter++, runner->izahl);
    18.             runner=runner->pnext;}
    19. }
    20.  
    21. void insert(Liste_izahlen **select, int iZahlinput){
    22.     Liste_izahlen *newelement=(Liste_izahlen*) malloc (sizeof(Liste_izahlen));
    23.     newelement->izahl=iZahlinput;
    24.     newelement->pnext=NULL;
    25.  
    26.     if (!*select)
    27.         *select=newelement;
    28.     else{
    29.         newelement->pnext=(*select)->pnext;
    30.         (*select)->pnext=newelement;}
    31. }
    32.  
    33.  
    34.  void insert_sort(Liste_izahlen **list, int iZahlinput){
    35.     Liste_izahlen **runner=*list;
    36.  
    37.     if (*runner)
    38.        while((iZahlinput>((*runner)->izahl))&&((*runner)->pnext!=NULL)&&(iZahlinput>((*runner)->pnext->izahl)))
    39.            *runner=(*runner)->pnext;
    40.     insert(&runner,iZahlinput);
    41. }
    42.  
    43. int main(void){
    44. int input=0;
    45. Liste_izahlen *xylist=NULL;
    46.  
    47. while(1){
    48.     printf("Geben Sie eine Ganzzahl ein: ");
    49.     if (scanf("%d", &input)){
    50.         insert_sort(&xylist,input);
    51.         print_list(xylist);
    52.     }
    53. }
    54. }
    55.  
    Danke euch Beiden, ihr habt mir schon mal geholfen etwas Klarheit in diesen Nebel zu bringen^^
  7. sheel

    sheel Mod # I love Asm Moderator

    Zum Abfangen vom NULL-Fall bei Insert:
    Jein.
    Es stimmt, das du beim Danach-Einfügen
    für das Einfügen am Anfang Was Leeres übergeben müsstest.
    Aber: Die Funktion denkt dann, dass noch keine Liste vorhanden ist (in dem Fall ist ja auch NULL).
    Als Next wird dann NULL eingetragen, auch wenn es schon eine gefüllte Liste gibt/gab.

    Wenns nicht im inser sein darf/kann muss man eben ggf. das Next außerhalb selbst setzen,
    wenn man was ganz am Anfang haben will.
    Zuerst ein Insert auf Leer und dann den Rest dazuhängen.


    Zum insert_sort: Geht es nach dem Beitrag von ibafluss oder noch immer nicht?
    Zumindest das Anfangs-Problem gibt es dann auch hier.
    Und beim Sortiert-sein wäre das wichtig.
  8. ibafluss

    ibafluss Erfahrenes Mitglied

    Du darfst bei der Zuweisung von runner keinen Stern bei list schreiben! Überprüfe jetzt noch einmal ganz genau ob mit den * und & operatoren alles stimmt, denn da ändert sich einiges. Poste dann noch einmal den neuen Code und was noch nicht funktioniert.

    Lg
  9. neuesich

    neuesich Grünschnabel

    So die Lösung kommt näher^^ Echt danke, ich war schon so verzweifelt...

    Es funktioniert alles soweit bis auf den erwähnten Fall, dass das einzufügende Element kleiner ist als das erste Element der Liste (Also davor einfügen). Da meine Aufgabenstellung vorgibt, dass insert_sort nur danach einfügen soll, hab ich versucht das in der insert_sort zu umgehen. Leider mit mäßigem Erfolg...

    Den Fall, dass beim ersten Aufruf eine Liste mit einem Element erstellt wird, habe ich wie vorgeschlagen mit einem ersten insert in der main umgesetzt.

    Hier mein derzeitiger Stand:
    Code (Text):
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3.  
    4. typedef struct list_izahl_element  {
    5.         int  izahl;
    6.         struct list_izahl_element *pnext;
    7.     } Liste_izahlen;
    8.  
    9.  
    10. void print_list(Liste_izahlen *list){
    11.     int counter=1;
    12.     Liste_izahlen* runner=list;
    13.  
    14.     if (!runner)
    15.         printf("Leere Liste!\n");
    16.     else
    17.         while (runner){
    18.             printf("%d. %d\n", counter++, runner->izahl);
    19.             runner=runner->pnext;}
    20. }
    21.  
    22. void insert(Liste_izahlen **select, int iZahlinput){
    23.     Liste_izahlen *newelement=(Liste_izahlen*) malloc (sizeof(Liste_izahlen));
    24.     newelement->izahl=iZahlinput;
    25.     newelement->pnext=NULL;
    26.  
    27.     if (!*select)
    28.         *select=newelement;
    29.     else{
    30.         newelement->pnext=(*select)->pnext;
    31.         (*select)->pnext=newelement;}
    32. }
    33.  
    34.  void insert_sort(Liste_izahlen **list, int iZahlinput){
    35.     Liste_izahlen **runner=list;
    36.  
    37.     if(((*runner)->izahl>iZahlinput)){
    38.         Liste_izahlen *newelement=(Liste_izahlen*) malloc (sizeof(Liste_izahlen));
    39.         newelement->izahl=iZahlinput;
    40.         newelement->pnext=*runner;
    41.         *runner=newelement;
    42.     }
    43.  
    44.     else{
    45.         while((iZahlinput>((*runner)->izahl))&&((*runner)->pnext!=NULL)&&(iZahlinput>((*runner)->pnext->izahl)))
    46.             *runner=(*runner)->pnext;
    47.         insert(runner,iZahlinput);}
    48. }
    49.  
    50. int main(void){
    51. int input=0;
    52. Liste_izahlen *xylist=NULL;
    53.  
    54. printf("Geben Sie eine Ganzzahl ein: ");
    55. if (scanf("%d", &input)){
    56.         insert(&xylist,input);
    57.         print_list(xylist);}
    58.  
    59. while(1){
    60.     printf("Geben Sie eine Ganzzahl ein: ");
    61.     if (scanf("%d", &input)){
    62.         insert_sort(&xylist,input);
    63.         print_list(xylist);}
    64. }
    65. }
    66.  
    lg
    Zuletzt bearbeitet: 17. April 2012
  10. sheel

    sheel Mod # I love Asm Moderator

    Zum ersten main-insert:
    Das
    Code (C++):
    1.  
    2. if (!*select)
    3.     *select=newelement;
    4. else
    5.  
    könntest du doch auch am Anfang von insert_sort machen? (Variablennamen anpassen)
    Die Nur-danach-einfügen-Regel wird dadurch nicht verletzt.
    Dann musst du für das erste Element im main keine Sonderbehandlung machen.

    Und wenn insert-sort unbedingt nichts davor einfügen darf,
    gleich nach dem oberen ersten if noch eine Abfrage, ob das erste vorhandene Element
    größer als das Neue ist.
    Wenn nein, weitermachen, sonst:
    Ein neues auf Leer anlegen (insert macht das ja gut),
    danach den Rest an Next hängen,
    return.
  11. neuesich

    neuesich Grünschnabel

    Hm ja es spricht nix dagegen, dass die insert_sort davor einfügt.
    Dann muss insert_sort drei Fälle beachten:
    1. Leere Liste => insert ausführen
    2. Einzufügendes Element < erstes Element => Element davoreinfügen
    3. Einzufügendes Element >= erstes Element => insert nutzen

    Mein Problem ist aber wie ich den ersten und zweiten Fall trenne. Wenn es nämlich eine leere Liste ist (NULL) und ich auf ein next-Element zugreife (Einzufügendes Element < erstes Element) knallt es bei der Bedingung, oder?
  12. sheel

    sheel Mod # I love Asm Moderator

    Das hier wird verwirrend :D

    Wenn man insert_sort NULL übergibt, wie kann es dann
    bei vorhandener Liste überhaupt Werte vergleichen?
    NULL darf nur kommen, wenn wirklich noch nichts da ist.
  13. neuesich

    neuesich Grünschnabel

    xD ja du hast recht. ich habe es jetzt direkt in der insert_sort. es funktioniert auch so weit alles gut. allerdings scheint es noch ein problem zu geben denn manchmal werden elemente weggeschnitten....

    //edit: so bald mehr als 3 elemente in der liste sind und ein wert an ende eingefügt werden soll (höchster wert), dann verschwinden alle elemente bis auf die letzten 2 der liste. d.h. bei
    Code (Text):
    1. *select=newelement;
    in der insert läuft was schief.
    zwischenstatus:
    Code (Text):
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3.  
    4. typedef struct list_izahl_element  {
    5.         int  izahl;
    6.         struct list_izahl_element *pnext;
    7.     } Liste_izahlen;
    8.  
    9. void print_list(Liste_izahlen *list){
    10.     int counter=1;
    11.     Liste_izahlen* runner=list;
    12.  
    13.     if (!runner)
    14.         printf("Leere Liste!\n");
    15.     else
    16.         while (runner){
    17.             printf("%d. %d\n", counter++, runner->izahl);
    18.             runner=runner->pnext;}
    19. }
    20.  
    21. void insert(Liste_izahlen **select, int iZahlinput){
    22.     Liste_izahlen *newelement=(Liste_izahlen*) malloc (sizeof(Liste_izahlen));
    23.     newelement->izahl=iZahlinput;
    24.     newelement->pnext=NULL;
    25.  
    26.     if (!*select)
    27.         *select=newelement;
    28.     else{
    29.         newelement->pnext=(*select)->pnext;
    30.         (*select)->pnext=newelement;}
    31. }
    32.  
    33.  void insert_sort(Liste_izahlen **list, int iZahlinput){
    34.     Liste_izahlen **runner=list;
    35.  
    36.     if(!*runner)
    37.         insert(runner,iZahlinput);
    38.  
    39.     else if(((*runner)->izahl>iZahlinput)){
    40.         Liste_izahlen *newelement=(Liste_izahlen*) malloc (sizeof(Liste_izahlen));
    41.         newelement->izahl=iZahlinput;
    42.         newelement->pnext=*runner;
    43.         *runner=newelement;}
    44.  
    45.     else{
    46.         while((iZahlinput>((*runner)->izahl)) && ((*runner)->pnext!=NULL) && (iZahlinput>((*runner)->pnext->izahl)))
    47.             *runner=(*runner)->pnext;
    48.         insert(runner,iZahlinput);
    49.     }
    50.  }
    51.  
    52. int main(void){
    53. int input=0;
    54. Liste_izahlen *xylist=NULL;
    55.  
    56. while(1){
    57.     printf("Geben Sie eine Ganzzahl ein: ");
    58.     if (scanf("%d", &input)){
    59.         insert_sort(&xylist,input);
    60.         print_list(xylist);}
    61. }
    62. }
    63.  
    Zuletzt bearbeitet: 17. April 2012
  14. ibafluss

    ibafluss Erfahrenes Mitglied

    Nein, der Fehler ist in insert_sort(). Wenn einmal Zeile 47 erreicht wird, änderst du, wenn du genauer hinsiehst, die Stelle, auf die xylist im main() zeigt. runner zeigt ja auf die xylist und wenn du dann schreibst:
    Code (C++):
    1. *runner =
    Dann veränderst du das, auf das runner zeigt, also xylist. Die Daten sind also schon vorhanden, nur hast du den Startpunkt verändert.
    Am besten erstellst du hier einen weiteren Pointer und erledigst das mit dem. Da das xylist nur bei dem Fall, dass es auf NULL zeigt, also die Liste leer ist, geändert werden darf, musst du das nur in Zeile 37 übergeben. In allen anderen Fällen sollte ein normaler Pointer zur Übergabe ausreichen, mit dem dann auch der Fehler in Zeile 47 behoben werden sollte.

    Lg
  15. neuesich

    neuesich Grünschnabel

    Also meine insert_sort sieht nun so aus:
    Code (Text):
    1.  void insert_sort(Liste_izahlen **list, int iZahlinput){
    2.     if(!*list)
    3.         insert(list,iZahlinput);
    4.  
    5.     else if(((*list)->izahl>iZahlinput)){
    6.         Liste_izahlen *newelement=(Liste_izahlen*) malloc (sizeof(Liste_izahlen));
    7.         newelement->izahl=iZahlinput;
    8.         newelement->pnext=*list;
    9.         *list=newelement;}
    10.  
    11.     else{
    12.         Liste_izahlen *runner=*list;
    13.         while((iZahlinput>runner->izahl) && (runner->pnext) && (iZahlinput>(runner->pnext->izahl)))
    14.             runner=runner->pnext;
    15.         insert(&runner,iZahlinput);
    16.     }
    17.  }
    18.  
    Ist auf jedenfall lauffähig und funktioniert so wie es soll ;) Danke für eure Hilfe!

Diese Seite empfehlen