Autor |
Beitrag |
Katy
Hält's aus hier
Beiträge: 9
Win ME
Delphi 7
|
Verfasst: Mi 13.09.06 15:10
Hallöchen!
Ich habe ein kleines (für mich eher großes  ) Problem. Unser Lehrer hat uns die Aufgabe gegeben, ein Programm zu schreiben, bei dem die Namen und Klassen von Schülern in eine Liste eingetragen werden sollen. Er hat uns offen gelassen, wo wir die Einträge anfügen, also habe ich mich für das Ende entschieden, wie bei der queue.
Der Einfachhalt halber habe ich erstmal nur eine Listbox benutzt, um die Einträge anzuzeigen. Hier der Quelltext:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52:
| var Form1: TForm1; Schule : pSchule; p, Erster, Letzter: pSchule; Liste, s, keyword : string;
implementation
{$R *.dfm}
procedure init; begin new(Erster); new(Letzter); Erster^.key := 'K'; Erster^.next := Letzter; Letzter^.next := NIL; Schule := Erster; end;
procedure Eintrag(var Schule : pSchule; s : string); begin new(Erster); new(Letzter); Erster^.key := s; Erster^.next := Letzter; Letzter^.next := Schule; Schule := Erster; end;
procedure TForm1.BEintragClick(Sender: TObject); begin new(p); p^.key := Form1.EEintrag.Text; if Letzter <> Nil then begin Letzter^.next := p; p^.next := Nil; Letzter := p; end else begin Erster := p; Letzter := p; end; Eintrag(Schule, s); Liste := p^.key; Form1.LBLSchueler.Items.Add(Liste); p := Erster^.next; p := p^.next; end; |
Nun muss ich einen Eintrag suchen und löschen können. Das soll ich aber nicht in der Listbox, sondern direkt in der Liste machen. Ich denke mal, ich benötige dazu nen Suchschlüssel, aber das ist leider auch schon alles, was ich weiß  . Hier mal mein (kläglicher) Versuch:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure TForm1.BSucheClick(Sender: TObject); begin new(p); keyword := Form1.ESuche.Text; while (p<>NIL) do begin if p.key = keyword then begin LBLSchueler.Items.Add(p.key); exit; end; p:=p^.next; end; end; |
- Wie kann ich einen über nen Editor eingebenen Namen suchen?
- Wie kann das gefundene Wort in der Listbox markiert werden?
- Und wie kann ich den Eintrag löschen?
Ich bräuchte dringend eure Hilfe, da ich das Programm am Freitag abgeben muss. Es wäre schön, wenn ihr auch möglichst meine Bezeichnungen verwenden könntet, denn ich will das Programm nicht nur fertig haben, ich möchte es auch verstehen.
mfg Katy
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Mi 13.09.06 15:25
Hallo Katy,
zunächst zum ersten Problem, suchen in der Liste: Geh deine Zeigerliste Zeiger für Zeiger durch und überprüfe ob der Name des aktuellen Zeiger mit dem des gesuchten übereinstimmt. Wenn ja, dann hast du ja die Position und die Werte des aktuellen Zeigers.
Ich denke, die Namen in der Liste sind in der selben Reihenfolge wie in der ListBox. Also hast du jetzt die Position. Mit ItemIndex kannst du jetzt die aktuelle Position selektieren. Wenn nicht, dann kannst du mit Items.IndexOf oder Items.Find (näheres dazu in der Hilfe) die Position finden und dann ItemIndex[7i] zuweisen.
Wenn du die Position weisst, dann kannst du das Item auch bequem über [i]Items.Delete löschen.
Items ist vom Typ TStrings und bietet sehr viele Methoden zum bearbeiten. Näheres auch in der Hilfe.
Hoffe geholfen zu haben, wenn es noch zu abstrakt war, bitte nachfragen!
Gruß Hape!
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
Katy 
Hält's aus hier
Beiträge: 9
Win ME
Delphi 7
|
Verfasst: Mi 13.09.06 16:00
Hi Hape!
Danke erstmal, dass du dich meinem Problem widmest.^^
Ich habe jetzt den Quelltext so geändert, dass der Zeiger p (für die Eingabe) mit dem Zeiger Erster verglichen wird.
Delphi-Quelltext 1: 2: 3:
| while (p <> NIL) do begin if p.key = Erster.key then |
Aber wo bekomm ich nun die Position her? Bei Itemindex brauche ich ja nen Integerwert, das bezieht sich doch auf die Position, oder?
mfg Katy
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Mi 13.09.06 16:34
Ja genau Katy, ItemIndex braucht eine Position.
Also wie gesagt, es gibt zwei Möglichkeiten:
Wenn die virtuelle Liste und die ListBox die selbe Reihenfolge haben, dann die aktuelle Position merken. Die Position solltest du bekommen, wenn du in der Suchschleife mit einer Zählvariable die durchgänge mitzählst.
Ansonsten, Find oder IndexOf benutzen  !
Gruß Hape!
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
Katy 
Hält's aus hier
Beiträge: 9
Win ME
Delphi 7
|
Verfasst: Mi 13.09.06 17:16
Hmm... gibt es vielleicht noch eine andere Möglichkeit außer mit ner Zählschleife und nem Index zu arbeiten? Unser Lehrer meinte (soweit ich mich erinnern kann), dass wir ohne Index und nur mit den Adressen arbeiten sollen.
Im Notfall würd ich es natürlich mit machen, besser, als gar nichts zu haben...
Aber ich komm mit dieser Zählschleife nicht klar.
Ich weiß, dass es irgendwie was mit for i = 0 to ? do sein muss, aber woher weiß ich die Größe der Liste, sprich die Anzahl? Außerdem sagt mir Delphi, dass i ne lokale Variable sein muss, dabei ist sie das!
mfg Katy
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Mi 13.09.06 17:39
Ok, ich geb dir mal ein bisschen Quelltext, vielleicht versteht du dann, was ich meine:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| var p: pSchule; I: Integer; begin I := 0; p := Erster; while Assigned(p) do begin if p^.key = SUCHWORT then Break; p := p^.next; Inc(I); end; | So in der Variable I hast du dann die Position, musst halt Aufpassen, dass du überprüfst ob der Eintrag überhaupt gefunden wurde, aber das überlasse ich jetzt dir.
Klar jetzt?
Gruß Hape!
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
Katy 
Hält's aus hier
Beiträge: 9
Win ME
Delphi 7
|
Verfasst: Mi 13.09.06 18:38
Jein...
Jetzt wird zwar ein Eintrag markiert, was schon mal sehr schön ist, aber nur irgendeiner und nicht der, der mit dem Wort übereinstimmt.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure TForm1.BSucheClick(Sender: TObject); var i : integer; p: pSchule; begin suchwort := Form1.ESuche.Text; i := 0; p := Erster; while assigned(p) do begin if p^.key = Suchwort then Break; p := p^.next; Inc(i); end; LBLSchueler.ItemIndex := i; end; |
Wenn du keine Lust mehr hast, kann ich das verstehen, ich hätte auch langsam die Schnauze voll...
mfg Katy
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Mi 13.09.06 19:01
Hallo Katy,
Geduld ist meine Spezialität, dass bekomm wir schon noch hin  !
Ich seh so auf die schnelle keinen Fehler, aber versuch mal selber drauf zu kommen: Delphi-Quelltext 1: 2: 3: 4: 5:
| if p^.key = Suchwort then begin ShowMessage(p^.key + ', ' + IntToStr(I)); Break; end; | Schau doch einfach mal, was hier kommt. Und wie gesagt, beide Listen müssen die selbe Reihenfolge haben. Stimmt das denn auch? Achja, beim nächsten Mal häng bitte noch die Definition von pSchule an!
Gruß Hape!
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
Katy 
Hält's aus hier
Beiträge: 9
Win ME
Delphi 7
|
Verfasst: Mi 13.09.06 19:29
Danke, ich dachte schon, du hast mich aufgegeben.
Hab's ausprobiert, aber er markiert wieder das falsche. Allerdings nun immer den 1. Eintrag.
Ich denke schon, dass beide Listen die gleiche Reihenfolge haben. Habe die Liste wie ne Schlange aufgebaut (siehe 1. Posting) und bei der Listbox wird ja automatisch immer hinten rangehangen.
Hier die Definition von pSchule:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| type pSchule = ^TSchule; TSchule = record key : string; next : pSchule; end; |
mfg Katy
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Mi 13.09.06 19:34
Ok, aber was sagt den nun die ShowMessage Prozedur, die ich eingebaut habe?
Weil irgendwie müssen wir den Fehler ja eingrenzen...Zur Not das ganze Programm zeigen 
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
Katy 
Hält's aus hier
Beiträge: 9
Win ME
Delphi 7
|
Verfasst: Mi 13.09.06 19:50
Sorry, das hatte ich vergessen...
Die Message kommt nicht! Nix! Das heißt also, dass der Zeiger und das Suchwort nie übereinstimmen. Ich teste aber natürlich nur Wörter, die auch wirklich in der Liste sind. Also muss ich doch irgendwo was verbockt haben...
Hier mal der ganze Quelltext (tut mir Leid...).
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112:
| unit USchule;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type pSchule = ^TSchule; TSchule = record key : string; next : pSchule; end;
TForm1 = class(TForm) LBLSchueler: TListBox; BEintrag: TButton; BSuche: TButton; Bweg: TButton; BBeenden: TButton; EEintrag: TEdit; ELoesch: TEdit; OpenDLG: TOpenDialog; SaveDlg: TSaveDialog; BSpeichern: TButton; BLaden: TButton; ESuche: TEdit; procedure BEintragClick(Sender: TObject); procedure BSucheClick(Sender: TObject);
private public end;
var Form1: TForm1; Schule : pSchule; p, Erster, Letzter: pSchule; Liste, s, Suchwort : string;
implementation
{$R *.dfm}
procedure init; begin new(Erster); new(Letzter); Erster^.key := 'K'; Erster^.next := Letzter; Letzter^.next := NIL; Schule := Erster; end;
procedure Eintrag(var Schule : pSchule; s : string); begin new(Erster); new(Letzter); Erster^.key := s; Erster^.next := Letzter; Letzter^.next := Schule; Schule := Erster; end;
procedure TForm1.BEintragClick(Sender: TObject); begin new(p); p^.key := Form1.EEintrag.Text; if Letzter <> Nil then begin Letzter^.next := p; p^.next := Nil; Letzter := p; end else begin Erster := p; Letzter := p; end; Eintrag(Schule, s); Liste := p^.key; Form1.LBLSchueler.Items.Add(Liste); p := Erster^.next; p := p^.next; end;
procedure TForm1.BSucheClick(Sender: TObject); var i : integer; p: pSchule; begin suchwort := Form1.ESuche.Text; i := 0; p := Erster; while assigned(p) do begin if p^.key = Suchwort then ShowMessage(p^.key + ', ' + IntToStr(I)); Break; p := p^.next; Inc(i); end; LBLSchueler.ItemIndex := i; end;
end. |
Oh Mann, ich mülle das Forum voll...
mfg Katy
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Mi 13.09.06 20:21
Also, ich hab dir unten mal die Lösung angehängt. Ich hab einiges verändert, ich hoffe du bist mir nicht Böse...
Das Problem ist, dass du relativ viele Variablen benutzt, was Anfänger gerne machen und dann den Überblick verlierst. Warum nie was gefunden wird, liegt daran, dass du in der Liste nie was hinzugefügt hast. Du hast das immer ganz umständlich über die Variable letzter gemacht, dabei brauchst du die gar nicht mehr.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68:
| var Erster: pSchule; implementation
{$R *.dfm}
procedure Eintrag(S: String); var p, neu: pSchule; begin New(neu); neu^.key := S; neu^.next := nil; p := Erster; if Assigned(p) then begin while Assigned(p^.next) do begin p := p^.next; end; p^.next := neu; end else erster := neu; end;
procedure TForm1.BEintragClick(Sender: TObject); begin Eintrag(EEintrag.Text); LBLSchueler.Items.Add(EEintrag.Text); end;
procedure TForm1.BSucheClick(Sender: TObject); var I: Integer; p: pSchule; gefunden: Boolean; begin p := Erster; gefunden := false; I := 0; while Assigned(p) do begin if p^.key = ESuche.Text then begin gefunden := true; break; end; p := p^.next; Inc(I); end; if gefunden then LBLSchueler.ItemIndex := I else LBLSchueler.ItemIndex := -1; end; |
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
Katy 
Hält's aus hier
Beiträge: 9
Win ME
Delphi 7
|
Verfasst: Mi 13.09.06 20:55
Woher weißt du, dass ich ein Anfänger bin?
Danke, dass du mir den Quelltext auch gleich erläuterst.
Also wir hatten in der Schule gelernt, dass wir für nen ADT immer ne Erzeugungs- und Zerstörungsroutine brauchen. Init war also die Initialisierung.
Wie kann ich das mit dem "Knoten" verstehen?
Ich wusste gar nicht, dass man bei der Ausgabe auch einfach den Editor angeben kann. Das ist natürlich spraktisch.  (das kann ich aber bestimmt nur beim Typ string, oder?)
Argh, das mit dem assigned habe ich nicht verstanden. Sowas hatten wir gar nicht...
Ich nehme mal an break ist einfach der Abbruch von der Schleife, oder? Wir hatten da immer nur was mit else... was es nicht gerade einfacher macht...
Zum Schluss setzt du gefunden also erstmal auf false, als Einstiegsbedingung. Wenn der Zeiger und das gesuchte Wort übereinstimmen, setzt du es auf wahr, weil die Bedingung dann erfüllt ist. Ganz zum Schluss hast du nur gefunden geschrieben, brauche ich da nichts weiter zuschreiben? Das es wahr ist?
Ich habe noch nicht ausprobiert, ob's funktoniert, aber das mache ich jetzt.
mfg Katy
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Mi 13.09.06 21:14
Katy hat folgendes geschrieben: | Woher weißt du, dass ich ein Anfänger bin?  |
Ach, war nur so geraten
Zitat: | Danke, dass du mir den Quelltext auch gleich erläuterst.  |
Bitte, ich will ja, dass du was dabei lernst  !
Zitat: | Also wir hatten in der Schule gelernt, dass wir für nen ADT immer ne Erzeugungs- und Zerstörungsroutine brauchen. Init war also die Initialisierung. |
Ich weiss eigentlich gar nicht was ADT bedeutet, aber ok. Initialisierung ist richtig, stimmt. Aber die sieht in dem Fall so aus, dass Erster auf nil gesetzt werden muss. Das hab ich vergessen. Wenn du was gutes tun willst, dann siehst du auch ob du es verstanden hast, dann schreib eine Prozedure Free, die den Speicher in der Liste wieder freigibt.
Zitat: | Wie kann ich das mit dem "Knoten" verstehen? |
Knoten war eigentlich der falsche Begriff, denn benutzt man bei Bäumen, aber das ist keiner. Ich meine eher den Listeintrag, also den Zeiger.
Zitat: | Ich wusste gar nicht, dass man bei der Ausgabe auch einfach den Editor angeben kann. Das ist natürlich spraktisch. (das kann ich aber bestimmt nur beim Typ string, oder?) |
Keine Ahnung was du meinst  .
Zitat: | Argh, das mit dem assigned habe ich nicht verstanden. Sowas hatten wir gar nicht... |
Ist das selbe wie folgender Vergleich: Delphi-Quelltext
Zitat: | Ich nehme mal an break ist einfach der Abbruch von der Schleife, oder? Wir hatten da immer nur was mit else... was es nicht gerade einfacher macht... |
Genau, break springt aus der Schleife und macht nach ihr weiter.
Zitat: | Ganz zum Schluss hast du nur gefunden geschrieben, brauche ich da nichts weiter zuschreiben? Das es wahr ist? |
Der Vergleich = true wird benutzt, wenn nichts angegeben wird.
Zitat: | Ich habe noch nicht ausprobiert, ob's funktoniert, aber das mache ich jetzt.  |
Ist getestet, sollte gehen  !
Gruß Hape!
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
Katy 
Hält's aus hier
Beiträge: 9
Win ME
Delphi 7
|
Verfasst: Mi 13.09.06 21:30
Zitat: | Zitat: | Also wir hatten in der Schule gelernt, dass wir für nen ADT immer ne Erzeugungs- und Zerstörungsroutine brauchen. Init war also die Initialisierung. | Ich weiss eigentlich gar nicht was ADT bedeutet, aber ok. Initialisierung ist richtig, stimmt. Aber die sieht in dem Fall so aus, dass Erster auf nil gesetzt werden muss. Das hab ich vergessen. Wenn du was gutes tun willst, dann siehst du auch ob du es verstanden hast, dann schreib eine Prozedure Free, die den Speicher in der Liste wieder freigibt. |
ADT heißt abstrakter Datentyp und meint damit stack, queue, list und den Baum. Sowas weiß ich, was man nicht wirklich braucht...
Zitat: | Zitat: | Ich wusste gar nicht, dass man bei der Ausgabe auch einfach den Editor angeben kann. Das ist natürlich spraktisch. (das kann ich aber bestimmt nur beim Typ string, oder?) | Keine Ahnung was du meinst . |
Du hast bei der Ausagabe einfach "LBLSchueler.Items.Add(EEintrag.Text);" geschrieben. Wir haben in den Klammern immer Variablen angegeben. Ich finde deine Variante da praktischer, macht nicht soviel Arbeit.
Zitat: | Zitat: | Argh, das mit dem assigned habe ich nicht verstanden. Sowas hatten wir gar nicht... | Ist das selbe wie folgender Vergleich: Delphi-Quelltext |
Toll, das gefällt mir. Damit kann ich was anfangen.
Zitat: | Zitat: | Ganz zum Schluss hast du nur gefunden geschrieben, brauche ich da nichts weiter zuschreiben? Das es wahr ist? | Der Vergleich = true wird benutzt, wenn nichts angegeben wird. |
Wie meinst du das...?
Das Programm funktioniert einwandfrei! Du bist ein Engel.
mfg Katy
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Mi 13.09.06 21:49
Katy hat folgendes geschrieben: | Wie meinst du das...? |
Na, dass man Vergleiche auf wahr (true) auch verkürzen kann, in dem man = true weglässt: Delphi-Quelltext 1: 2: 3:
| if gefunden = true then if gefunden then | Gruß Hape!
Edit: Variable umbenannt, damit die Bezeichnung durchgängig ist.
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
Katy 
Hält's aus hier
Beiträge: 9
Win ME
Delphi 7
|
Verfasst: Mi 13.09.06 21:55
Okay, dann ist gut. Gucke mir das morgen alles noch mal intensiv an und versuche auch diese Prozedur Free aufzustellen, mit dem Leeren des Speichers. Und das Löschen, das kann ja nicht mehr so schwer sein.
Du hast mir wirklich sehr geholfen, vielen Dank.
mfg Katy
|
|
|