Löschen eines Elements aus der Liste

  • #1
R

ripezone

Neues Mitglied
Themenersteller
Dabei seit
18.03.2006
Beiträge
1
Reaktionspunkte
0
hello
ich hab ein->'kleines'' problem ich bin noch ziemlicher anfänger in C++ Programmierung und hab mich jetzt ein bisschen mit der einfach verketteten Liste gespielt

Mein Porgramm:

/*
Programm: Einfach verkettete Liste

Aufgaben:
            1. Einfügen am Anfang
            2. Anhängen am Ende
            3. Ausgabe am Bildschirm
            4. Einlesen von einer Datei
            5. Ausgabe in eine Datei
            6. Suchen nach Strasse
            7. Löschen nach Nachname
            8. Löschen nach Nachname
            9. Löschen nach Land
           
*/

#include <iostream.h>
#include <conio.h>
#include <malloc.h>

struct mitglied                             //Datenstruktur
{
    char vorname[20];
    char nachname[20];
    char strasse[20];
    char land[20];
    int hausnummer;
    char kontonummer[20];
    mitglied*next;
};

void einfuganfg(mitglied *(*start));        //Prototyp Einfügen am Anfang
void anhaengenende(mitglied *(*start));     //Prototyp Anhängen am Ende
void ausgabe(mitglied *start);              //Prototyp Ausgabe am Bildschirm
void einlesendatei(mitglied *(*start));     //Prototyp Einlesen von Datei
void ausgabedatei(mitglied *start);         //Prototyp Ausgabe in Datei
void suchenstrasse(mitglied *(*start));     //Prototyp Suchen nach Straße
void suchenhausnummer(mitglied *(*start));  //Prototyp Suchen nach Hausnummer
void loeschennachname(mitglied *(*start));  //Prototyp Löschen nach Nachname
void loeschenland(mitglied *(*start));      //Prototyp Löschen nach Land
void einfuganfg(mitglied *(*start))         //Unterprogramm Einfügen am Anfang
{
    mitglied *p;                            //Hilfspointer
    char auswahl;
   
    do
    {
    p=(mitglied*)malloc(sizeof(mitglied));  //Größe des Hilfspointers bestimmen
    cout<<Vorname: ;                     //Einlesen der einzelnen geforderten Daten
    cin>>(*p).vorname;
    cout<<Nachname: ;
    cin>>(*p).nachname;
    cout<<Strasse: ;
    cin>>(*p).strasse;
    cout<<Hausnummer: ;
    cin>>(*p).hausnummer;
    cout<<Land: ;
    cin>>(*p).land;
    cout<<Kontonummer: ;
    cin>>(*p).kontonummer;
    (*p).next=*start;
    *start=p;
    cout<<Wiederholen j/n????: ;
    cin>>auswahl;
    }while(auswahl=='j');
};
void anhaengenende(mitglied *(*start))    //Unterprogramm Anhängen am Schluss
{   mitglied *p;                          //Erster Hilfspointer
    mitglied *h;                          //Zweiter Hilfspointer
   
    char auswahl;
    do
    {
    h=(mitglied*)malloc(sizeof(mitglied)); 
    cout<<Vorname: ;
    cin>>(*h).vorname;
    cout<<Nachname: ;
    cin>>(*h).nachname;
    cout<<Strasse: ;
    cin>>(*h).strasse;
    cout<<Hausnummer: ;
    cin>>(*h).hausnummer;
    cout<<Land: ;
    cin>>(*h).land;
    cout<<Kontonummer: ;
    cin>>(*h).kontonummer;
    if(*start==0)                           
    {                                       
        *start=h;
        (*h).next=0;
    }
    else
    {
        p=*start;
        while((*p).next!=0)
        {
            p=(*p).next;
        }
        (*p).next=h;
        (*h).next=0;
    }
    cout<<Wiederholen j/n????: ;
    cin>>auswahl;
    }while(auswahl=='j');   
}
void ausgabe(mitglied *start)     //Unterprogramm Ausgabe am Bildschirm
{   mitglied *p;                  //Hilfspointer
    p=start;
    do
    {
    cout<<Vorname: <<(*p).vorname<<\n;
    cout<<Nachname: <<(*p).nachname<<\n;
    cout<<Strasse: <<(*p).strasse<<\n;
    cout<<Hausnummer: <<(*p).hausnummer<<\n;
    cout<<Land: <<(*p).land<<\n;
    cout<<Kontonummer: <<(*p).kontonummer<<\n\n\n;
    p=(*p).next;
    }while(p!=0);
};
void einlesendatei(mitglied *(*start)) //Unterprogramm Einlesen von Datei
{   
    mitglied *p;                        //Hilfspointer
    FILE*datei;                        //Filepointer
    datei=fopen(C:\\Dokumente und Einstellungen\\Admin\\Eigene Dateien\\_Schule\\_3aheli\\AINF\\auspj1.txt,r);//Datei öffnen zum Lesen
    if(datei==0)
    { cout<<datei konnte nicht geoffnet werden;
    }
    while(!feof(datei))
    {
    p=(mitglied*)malloc(sizeof(mitglied));
    fscanf(datei,%s\n,(*p).vorname);
    fscanf(datei,%s\n,(*p).nachname);
    fscanf(datei,%s\n,(*p).strasse);
    fscanf(datei,%d\n,&(*p).hausnummer);
    fscanf(datei,%s\n,(*p).land);
    fscanf(datei,%s\n,(*p).kontonummer);
    (*p).next=*start;
    *start=p;
    };
    fclose(datei);    //Datei schließen
   
};
void ausgabedatei(mitglied *start) //Unterprogramm Ausgabe in Datei
{   mitglied *p;    //Hilfspointer
    FILE*datei;
    char um=10;     //Zeilenumbruch
    datei=fopen(C:\\Dokumente und Einstellungen\\Admin\\Eigene Dateien\\_Schule\\_3aheli\\AINF\\auspj1.txt,w); //Datei öffnen zum schreiben
    p=start;
    do
    {
    fputs((*p).vorname,datei);
    fputc(um,datei);
    fputs((*p).nachname,datei);
    fputc(um,datei);
    fputs((*p).strasse,datei);
    fputc(um,datei);
    fprintf(datei,%d,(*p).hausnummer);
    fputc(um,datei);
    fputs((*p).land,datei);
    fputc(um,datei);
    fputs((*p).kontonummer,datei);
    fputc(um,datei);
    fputc(um,datei);
    p=(*p).next;
    }while(p!=0);
    fclose(datei);    //Datei schließen
};
void suchenstrasse(mitglied *(*start))    //Unterprogramm zum Suchen nach Strasse
{
    char strasse[20];
    mitglied *p;    //Hilfspointer
    p=*start;
    cout<<Welche Strasse wird gesucht?? ;
    gets(strasse);
    do
    {
        if(strcmp(strasse,(*p).strasse))    //Vergleich der beiden Strings
        {
        }
        else
        {
                cout<<(*p).vorname<<\n;
                cout<<(*p).nachname<<\n;
                cout<<(*p).strasse<<\n;
                cout<<(*p).hausnummer<<\n;
                cout<<(*p).land<<\n;
                cout<<(*p).kontonummer<<\n;
        }
       
    p=(*p).next;
    }while(p!=0);
}
void suchenhausnummer(mitglied *(*start))           //Unterprogramm zum Suchen nach Hausnummer
{
    int hausnummer;
    mitglied *p;    //Hilfspointer
    p=*start;
    cout<<Welche Hausnummer wird gesucht?? ;
    cin>>hausnummer;
    do
    {
        if(hausnummer==(*p).hausnummer)    //Vergleich ob die gesuchte Hausnummer gleich der vorhandenen Hausnummer ist
        {
                cout<<(*p).vorname<<\n;
                cout<<(*p).nachname<<\n;
                cout<<(*p).strasse<<\n;
                cout<<(*p).hausnummer<<\n;
                cout<<(*p).land<<\n;
                cout<<(*p).kontonummer<<\n;
        }
       
    p=(*p).next;
    }while(p!=0);
}
void loeschennachname(mitglied *(*start))           //Unterprogramm zum Löschen nach Nachname
{char nachname[20];
    mitglied *p;    //Erster Hilfspointer
    mitglied *h;    //Zweiter Hilfspointer     
    p=*start;
    int i=0;
    cout<<Loeschen nach Nachname?? ;
    cin>>nachname;
   
        if(strcmp(nachname,(*p).nachname))  //Vergleich der beiden Strings
        {
        }
        else
        {
          if (p == NULL)    // überprüfen, ob Liste noch leer ist
          {cout<<Liste ist leer!);   
          }
        else
        { 
     h = (*p).next; 
                                                           
     (*p).next = (*h).next;
     free (p);         
      }
               
        }
 
}
void loeschenland(mitglied *(*start))        //Unterprogramm zum Löschen nach Land
{char land[20];
int i=0;
    mitglied *p;    //Erster Hilfspointer
    mitglied *h;    //Zweiter Hilfspointer
    p=*start;
    cout<<Loeschen nach Land?? ;
    cin>>land;
    do
    {
        if(strcmp(land,(*p).land))    //Vergleich der beiden Strings
        {
        }
        else
        {h = (*p).next;
                (*p).next=(*h).next;
                free(p);
               
        }
   
    }while(p!=0);
}

int main()      //Hauptprogramm
{
    mitglied*p; //Hilfspointer
    mitglied*start;    //Startpointer
    int auswahl;
    start=0;

    do
    {
    cout<<\nProgramm: Einfach verkettete Liste\n;    //Menüauswahl
    cout<<Menue: \n\t1.)Einfuegen am Anfang;
    cout<<\n\t2.)Anhaengen am Ende;
    cout<<\n\t3.)Ausgabe am Bildschirm;
    cout<<\n\t4.)Einlesen von einer Datei;
    cout<<\n\t5.)Ausgabe in eine Datei\n\t;
    cout<<6.)Suchen nach Strasse\n\t;
    cout<<7.)Suchen nach Hausnummer;
    cout<<\n\t8.)Loeschen nach Nachname;
    cout<<\n\t9.)Löschen nach Land;
    cout<<\n\t10.)Beenden;
    cout<<\nAuswahl: ;
    cin>>auswahl;
       
        switch(auswahl)            //Mehrfachauswahl für die Unterprogramme
        {
        case 1:
                einfuganfg(&start);
                break;
   
        case 2:
                anhaengenende(&start);
                break;
       
        case 3:
                ausgabe(start);
                break;
               
        case 4:
                einlesendatei(&start);
                break;
               
        case 5:
                ausgabedatei(start);
                break;
       
        case 6:
                suchenstrasse(&start);
                break;
               
        case 7:
                suchenhausnummer(&start);
                break;
               
        case 8:
                loeschennachname(&start);
                break;
               
        case 9:
                loeschenland(&start);
                break;
        }
   }while(auswahl!=10);
   
getch();
}
ich hab probleme beim löschen nach nachname und beim löschen nach land, das programm macht nämlich überhaupt nichts
vl könnt ihr mir helfen
wer echt super
danke
 
  • #2
So (z.B.) müsste es funktionieren:
In der Funktion ausgabe dies hier vor do setzen (start ohne Sternchen, unten mit):
Code:
  if(start == 0) {
    cout << Die Liste ist leer. << endl;
  } else

Code:
// Löschen des ersten Eintrags mit dem entsprechenden Nachnamen.
void loeschennachname(mitglied** start)   
{
    
  if (*start == 0) {
    cout << Liste ist leer. << endl;
    return;
  }

  char nachname[20];  
  cout << Loeschen nach Nachname: ;
  // Unsichere Eingabe
  cin >> nachname;  
  
  mitglied* aktuell= *start;        // Erster Hilfspointer
  mitglied* nachlauf= aktuell;    // Zweiter Hilfspointer     

  if(!strcmp(nachname, aktuell->nachname))
    // Startzeiger auf das dem aktuellen Element folgende Element setzen (*)
    *start= aktuell->next;
  else {
    aktuell= aktuell->next;
    while(aktuell) {
      if(!strcmp(nachname, aktuell->nachname)) {
        //->next' des vorigen Elementes auf das nächste Element setzen (*)
        nachlauf->next= aktuell->next;
        break;
      }
      nachlauf= aktuell;
      aktuell= aktuell->next;
    };    
  }

  if(aktuell == 0)
    cout << Es wurde kein Mitglied mit dem Nachnamen \ << nachname << \ gefunden. << endl;
  else
    // Hinweis: free ist auch mit einem 0-Zeiger sicher; aber da wir hier wegen der Meldung eh abfragen ...
    free(aktuell);  
}

(*)
Wichtig zum Verständnis: Das zu löschende Element wird damit in der Liste übersprungen, es wird also aus der Liste entfernt.

Beispiel:

start -> E1 -> E2 -> E3
'aktuell' zeigt auf E2

Das Entfernen von Element 2 aus der Liste bedeutet nun lediglich, E1.next auf E3 zu setzen.

start -> E1 -> E3
'aktuell' zeigt immer noch auf E2

E2 selbst existiert aber trotzdem noch im Speicher; die Adresse von E2 befindet sich nur noch in->aktuell'. Würden wir das Element weiter unten nicht löschen (free), würde die Liste zwar korrekt funktionieren, aber es würde ein Speicherleck entstehen, da wir nicht mehr auf E2 zugreifen könnten.

Wir verlassen die Funktion, ohne E2 zu löschen ...
start -> E1 -> E3
'aktuell' ruht bis zur nächsten Reinkarnation in den ewigen Bytegründen
                               E2s letzte Worte: Es ist einsam in den endlosen Weiten des Speichers. Da draußen hört dich niemand schreien, wenn->aktuell' sich unter den Acker gemacht hat [Regieanweisung: immer leiser werdend]) (**)

(**) Sorry, ich habe 39,1°C Fieber

Erst beim Programmende würde der Speicher, den E2 belegt, vom Betriebssystem automatisch freigegeben.

Noch zum Original:
Code:
// Hier vergleichst Du (verwendest also p) ...
if(strcmp(nachname, (*p).nachname))
{

}
else
{ // ... und schaust dann anschließend nach, ob p überhaupt gültig ist.
  if (p == NULL) 
  {
    cout<<Liste ist leer!);   
  }
  else {  
    h= (*p).next;  
    // Hier wird->next' von p geändert [es muss aber nicht->next' des aktuellen Elementes,
    // sondern->next' des vorigen Elementes gesetzt werden]
    (*p).next = (*h).next;
    // Hier wird p dann gelöscht (dann war die Änderung oben auch sinnlos, egal ob richtig oder falsch).
    free (p);         
  }
  // Und das war es dann auch; Du vergleichst nur das erste Element.
}

Bei der anderen Funktion musst Du die ganze Liste durchgehen, wenn Du alle Einträge mit->Land gleich XYZ' löschen willst. Das wäre mit den Nachnamen weniger sinnvoll (d.h. mehr Aufwand, aber nicht sinnvoller als oben).
 
Thema:

Löschen eines Elements aus der Liste

ANGEBOTE & SPONSOREN

Statistik des Forums

Themen
113.838
Beiträge
707.961
Mitglieder
51.491
Neuestes Mitglied
haraldmuc
Oben