![]() |
Name aus Liste löschen
Hi!
Wir realisieren im Informatikunterricht z.Z. eine Liste mit Namen, die eingegeben und gelöscht werden können (alles mit Hilfe von Zeigern), folgendermaßen aufgebaut: Zwei Listboxes (eine für die Platzierung, da es sich bei der Liste um Skispringer handelt und für den Namen und eine für die zum Namen zugehörige Wertung) und zwei Buttons, nächster Springer und Springer löschen. Bei Klick auf nächster Springer erscheinen zwei InputBoxes, zuerst eine für den Namen und danach eine für die zugehörige Wertung. Nach diesen Einträgen werden der Name und die Wertung gespeichert und sortiert nach Wertung in die jeweiligen Listboxes eingetragen. Die Procedure hierzu ist folgende (zu oberst die Deklaration der globalen Variablen):
Delphi-Quellcode:
type
TZeiger = ^TSpringer; TSpringer = record name : String; wertung : Real; vorher, nachher : TZeiger end; var Skispringen : TSkispringen; oben : TZeiger; platz : Integer;
Delphi-Quellcode:
Und hier die Procedure zum ausgeben:
procedure TSkispringen.bt_naechster_springerClick(Sender: TObject);
var aktuell, hilf, lauf : TZeiger; begin new(aktuell); aktuell^.name := InputBox('Eingabe','Name',''); aktuell^.wertung := StrToFloat(InputBox('Eingabe','Wertung','')); aktuell^.vorher := nil; aktuell^.nachher := nil; IF oben = nil THEN oben := aktuell ELSE begin IF aktuell^.wertung > oben^.wertung THEN begin oben^.vorher := aktuell; aktuell^.nachher := oben; oben := aktuell end ELSE begin lauf := oben; WHILE (lauf^.wertung > aktuell^.wertung) AND (lauf^.nachher <> nil) DO lauf := lauf^.nachher; IF (aktuell^.wertung > lauf^.wertung) THEN begin aktuell^.vorher := lauf^.vorher; aktuell^.nachher := lauf; hilf := lauf^.vorher; hilf^.nachher := aktuell; lauf^.vorher := aktuell end ELSE begin lauf^.nachher := aktuell; aktuell^.vorher := lauf end end end; ausgabe end;
Delphi-Quellcode:
Soweit, so gut. Klappt auch alles ohne Probleme. Nun habe ich mich eben hingesetzt und den Algorithmus programmiert, um einen Springer anhand seines Namens zu löschen:
procedure TSkispringen.ausgabe;
var hilf : TZeiger; begin li_skispringer.Clear; li_wertung.Clear; hilf := oben; platz := 0; WHILE (hilf <> nil) DO begin inc(platz); li_skispringer.Items.Add(IntToStr(platz) + '. ' + hilf^.name); li_wertung.Items.Add(FloatToStr(hilf^.wertung)); hilf := hilf^.nachher; end end;
Delphi-Quellcode:
Hier hört das Programm leider auf zu funktionieren. Ich kann zwar den zu löschenden Namen eingeben, aber leider wird dieser nicht aus der Listbox gelöscht und ich komme einfach nicht drauf, wieso nicht. Ich hoffe, ich hab das verständlich erklärt und es kann mir jemand helfen.
procedure TSkispringen.bt_springer_loeschenClick(Sender: TObject);
var lauf : TZeiger; such : String; begin such := InputBox('Eingabe','Name',''); lauf := oben; WHILE NOT (lauf^.nachher = nil) AND (such = lauf^.name) DO lauf := lauf^.nachher; IF (lauf^.name = such) AND (lauf^.nachher = nil) THEN lauf^.vorher^.nachher := nil ELSE IF such = lauf^.name THEN begin lauf^.vorher^.nachher := lauf^.nachher; lauf^.nachher^.vorher := lauf^.vorher end ELSE IF such = oben^.name THEN oben^.nachher^.vorher := nil; // ELSE exit; ausgabe end; Gruß, Olli P.S.: Ich weiß, dass sowas auch einfacher zu realisieren ist, aber wir müssen halt mit Zeigern arbeiten ... |
Re: Name aus Liste löschen
Hi,
der Fehler liegt hier:
Delphi-Quellcode:
Funktionieren sollte es mit einem zweiten NOT nach dem AND oder einfacher so:
WHILE NOT (lauf^.nachher = nil) AND (such = lauf^.name) DO
Delphi-Quellcode:
WHILE (lauf^.nachher <> nil) AND (such <> lauf^.name) DO
|
Re: Name aus Liste löschen
Vielen Dank, jetzt funktioniert's! Ich wusste nicht, dass ich das NOT zweimal verwenden muss - wieder was gelernt, danke!
Gruß, Olli |
Re: Name aus Liste löschen
Statt such = lauf^.name würde ich hier AnsiCompareText verwenden, dann spielt die Groß-/Kleinschreibung keine Rolle mehr, und statt zweimal not würd auch ein Klammernpaar um die beiden Bedingungen reichen.
P.S.: Zeigertypen werden eigentlich mit P... deklariert (also PSpringer), wenn TZeiger aber vom Lehrer kommt... :| |
Re: Name aus Liste löschen
So, hab noch was weiterprogrammiert und bin direkt beim nächsten Fehler angelangt: Wenn ich das erste Element in der Liste löschen will, kommt zwar keine Fehlermeldung, das Element wird aber auch nicht aus der Listbox entfernt. Wenn ich daraufhin das nachfolgende Element löschen will, ist dieses angeblich nicht mehr in der Liste.
Ähnliches, wenn ich ein einziges Element aus der Listbox löschen will, ohne, dass noch andere vorhanden sind. Wenn ich das versuche, kommt ein Fehler und das Programm stürzt ab. Hier mal mein etwas veränderter Lösch-Algorithmus (der Rest ist gleich geblieben):
Delphi-Quellcode:
P.S.: Ich glaube, ich spreche das oberste Element falsch an, denn wenn ich nur ein einziges Element in der Liste habe und dieses löschen will, bricht das Programm ab und markiert die Zeile
procedure TSkispringen.bt_springer_loeschenClick(Sender: TObject);
var lauf : TZeiger; such : String; begin such := InputBox('Eingabe','Name',''); lauf := oben; WHILE (lauf^.nachher <> nil) AND (such <> lauf^.name) DO lauf := lauf^.nachher; IF (lauf^.name = such) AND (lauf^.nachher = nil) AND (lauf^.vorher <> nil) THEN // letztes Element lauf^.vorher^.nachher := nil ELSE IF (such = lauf^.name) AND (lauf^.vorher <> nil) AND (lauf^.nachher <> nil) THEN // nicht erstes/letztes Element begin lauf^.vorher^.nachher := lauf^.nachher; lauf^.nachher^.vorher := lauf^.vorher end ELSE IF such = oben^.name THEN // erstes Element oben^.nachher^.vorher := nil ELSE begin ShowMessage('Springer nicht in der Liste!'); exit end; ausgabe end;
Delphi-Quellcode:
!
oben^.nachher^.vorher := nil
P.S.: Das TZeiger kam tatsächlich vom Lehrer ;) |
Re: Name aus Liste löschen
Ich hab' deine if's mal ein bisschen entwirrt :wink:
Delphi-Quellcode:
[edit] Free in Dispose geändert. [/edit]
// ...
while (lauf^.nachher <> nil) and (such <> lauf^.name) do lauf := lauf^.nachher; if (lauf^.name = such) then begin if (lauf = oben) then oben := lauf^.nachher else lauf^.vorher^.nachher := lauf^.nachher; if (lauf^.nachher <> nil) then lauf^.nachher^.vorher := lauf^.vorher; Dispose(lauf); ausgabe; end else ShowMessage('Springer nicht in der Liste!'); |
Re: Name aus Liste löschen
Hallo Olli,
deine Suchschleife für die doppelt verkettete Liste sieht noch etwas merkwürdig aus. Für eine solche Funktion überlegt man sich - wie stets - was geht rein, was soll raus kommen? such ist konstant, lauf ist variabel. Die Vorbedingung für lauf ist "lauf = oben", das hast du schon mal richtig gemacht. Hast du dir eigentlich jemals Gedanken über die Nachbedingung gemacht?
Delphi-Quellcode:
Grüße vom marabu
procedure TSkispringen.bt_springer_loeschenClick(Sender: TObject);
var lauf: TZeiger; such: String; BEGIN such := InputBox('Eingabe', 'Name', ''); // precondition: lauf = oben lauf := oben; WHILE (lauf <> nil) AND (such <> lauf^.name) DO lauf := lauf^.nachher; // postcondition: // lauf = nil g.d.w. nicht gefunden // lauf <> nil g.d.w. lauf^.name = such // Und auch der eigentliche Aktionsteil // sieht aufgeräumt aus, wenn du weißt, was du tust IF NichtGefunden THEN ShowMessage('hä?') ELSE BEGIN IF EsGibtEinenNachfolger THEN lauf^.nachher^.vorher := lauf^.vorher; IF EsGibtEinenVorggänger THEN lauf^.vorher^.nachher := lauf^.nachher ELSE EsGibtEinenNeuenErsten; // Kannst Speicher ruhig wieder freigeben // Brauchst ihn ja doch nicht mehr Dispose(lauf); Ausgabe(); END; END; |
Re: Name aus Liste löschen
Vielen Dank für eure Hilfe. Mit Nikos verbessertem Code funktioniert es (außer der Funktion free: "Zu viele Parameter", aber das liegt wohl daran, dass wir mit dem alten Delphi 4 arbeiten.
Ich habe dann die Funktion dispose benutzt, die das selbe bewirkt wie free, oder? Auf jeden fall danke für eure Hilfe! |
Re: Name aus Liste löschen
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz