AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Name aus Liste löschen

Ein Thema von der olli · begonnen am 14. Nov 2005 · letzter Beitrag vom 15. Nov 2005
Antwort Antwort
der olli

Registriert seit: 18. Mai 2004
14 Beiträge
 
#1

Name aus Liste löschen

  Alt 14. Nov 2005, 19:36
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:
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;
Und hier die Procedure zum ausgeben:
Delphi-Quellcode:
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;
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:
Delphi-Quellcode:
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;
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.

Gruß,
Olli

P.S.: Ich weiß, dass sowas auch einfacher zu realisieren ist, aber wir müssen halt mit Zeigern arbeiten ...
  Mit Zitat antworten Zitat
Niko

Registriert seit: 23. Jun 2003
416 Beiträge
 
Delphi 2006 Professional
 
#2

Re: Name aus Liste löschen

  Alt 14. Nov 2005, 20:08
Hi,

der Fehler liegt hier:WHILE NOT (lauf^.nachher = nil) AND (such = lauf^.name) DO Funktionieren sollte es mit einem zweiten NOT nach dem AND oder einfacher so:WHILE (lauf^.nachher <> nil) AND (such <> lauf^.name) DO
"Electricity is actually made up of extremely tiny particles called electrons, that you cannot see with the naked eye unless you have been drinking." (Dave Barry)
  Mit Zitat antworten Zitat
der olli

Registriert seit: 18. Mai 2004
14 Beiträge
 
#3

Re: Name aus Liste löschen

  Alt 14. Nov 2005, 20:23
Vielen Dank, jetzt funktioniert's! Ich wusste nicht, dass ich das NOT zweimal verwenden muss - wieder was gelernt, danke!

Gruß,
Olli
  Mit Zitat antworten Zitat
Phistev
(Gast)

n/a Beiträge
 
#4

Re: Name aus Liste löschen

  Alt 14. Nov 2005, 20:46
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...
  Mit Zitat antworten Zitat
der olli

Registriert seit: 18. Mai 2004
14 Beiträge
 
#5

Re: Name aus Liste löschen

  Alt 14. Nov 2005, 21:02
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:
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;
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 oben^.nachher^.vorher := nil !

P.S.: Das TZeiger kam tatsächlich vom Lehrer
  Mit Zitat antworten Zitat
Niko

Registriert seit: 23. Jun 2003
416 Beiträge
 
Delphi 2006 Professional
 
#6

Re: Name aus Liste löschen

  Alt 14. Nov 2005, 22:07
Ich hab' deine if's mal ein bisschen entwirrt
Delphi-Quellcode:
// ...
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!');
[edit] Free in Dispose geändert. [/edit]
"Electricity is actually made up of extremely tiny particles called electrons, that you cannot see with the naked eye unless you have been drinking." (Dave Barry)
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#7

Re: Name aus Liste löschen

  Alt 14. Nov 2005, 22:25
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:
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;
Grüße vom marabu
  Mit Zitat antworten Zitat
der olli

Registriert seit: 18. Mai 2004
14 Beiträge
 
#8

Re: Name aus Liste löschen

  Alt 14. Nov 2005, 22:43
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!
  Mit Zitat antworten Zitat
Niko

Registriert seit: 23. Jun 2003
416 Beiträge
 
Delphi 2006 Professional
 
#9

Re: Name aus Liste löschen

  Alt 15. Nov 2005, 20:01
Zitat von der olli:
(außer der Funktion free: "Zu viele Parameter", aber das liegt wohl daran, dass wir mit dem alten Delphi 4 arbeiten.
Nein, das liegt einfach daran, dass ich in letzter Zeit mehr mit C als mit Delphi zu tun hatte - Dispose ist die richtige Funktion.
"Electricity is actually made up of extremely tiny particles called electrons, that you cannot see with the naked eye unless you have been drinking." (Dave Barry)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz