| Autor |
Beitrag |
Elite
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 10.07.04 12:17
Hallo,
Ich bin dabei ein kleines Verwaltungsprogramm zu schreiben. Um einträge zu löschen, müsste ich wissen, wie ich aus einem dynamischen Array ein Element "heraustrenne". Praktisch so, dass die übrigen Elemente eins aufrutschen.
Delphi-Quelltext 1: 2:
| var Liste: array of TDatenRec; SetLength(Liste, 20); |
Nun soll z.B. das 10. Element enternt werden und die Liste soll danach noch 19 Elemente haben.
Dankeim Voraus! Moderiert von Peter Lustig: Topic aus VCL (Visual Component Library) verschoben am Sa 10.07.2004 um 12:20
|
|
Schattengeist
      
Beiträge: 29
|
Verfasst: Sa 10.07.04 12:20
'per Hand'
Alle hochrücken, dann die Liste kürzen.
Hmmm. Wir verwenden für sowas StingListen/ObjektListen. Da ist sowas alles schon drin. Man muß nur das alles als Objekte vorliegen haben.
|
|
Muetze1
      
Beiträge: 346
|
Verfasst: Sa 10.07.04 12:39
Moin!
Wieso Objekte? Nimm TList und dann kannste das gleiche auch mit deinen Records machen...
MfG
Muetze1
|
|
bms
      
Beiträge: 735
Win XP
Delphi 3, Delphi 6 PE, Delphi 2005 PE
|
Verfasst: Sa 10.07.04 12:56
| Elite* hat folgendes geschrieben: | Um einträge zu löschen, müsste ich wissen, wie ich aus einem dynamischen Array ein Element "heraustrenne". Praktisch so, dass die übrigen Elemente eins aufrutschen.
Delphi-Quelltext 1: 2:
| var Liste: array of TDatenRec; SetLength(Liste, 20); |
Nun soll z.B. das 10. Element enternt werden und die Liste soll danach noch 19 Elemente haben. |
Wie gesagt per Hand. Allerdings kannst du das ein wenig anders angehen. Du löscht den Wert nicht, sondern gibst ihm eine Löschmarke. In deinem Programm achtest du dann, daß du nur Werte verwendest die keine Löschmarke haben. Zur gegebner Zeit kann der User dann die Datenbank komprimieren. Hier wird dann nicht gezipt, sondern der Array wird von gelöschten Werten befreit. Anders machen es übrigens auch die Datenbanken nicht. Sie belassen die gelöschten Werte und löschen die erst wenn die Datenbank komprimiert wird.
_________________ VORSICHT: Ich behersche seit heute die Fünf-Finger-Handflächen-Herz-Explodier-Schlag-Kampf-Technik >
|
|
Schattengeist
      
Beiträge: 29
|
Verfasst: Sa 10.07.04 13:02
Da es sich nur um Speichertabellen handelt, finde ich, das Löschmarken etwas zu aufwendig sind.
Mal eben kurz das zu eleminieren sollte nicht soooo zeitfressend sein.
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 480
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 10.07.04 13:45
naja...für solche Operationen würde ich trotzdem dringendst ein Listenstruktur empfehlen. Besonders dann, wenn solche Lösch- (und Einfüge-) operationen öfter auftreten, und die Anzahl der Objekte groß ist.
_________________ We are, we were and will not be.
|
|
Elite
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 10.07.04 17:39
Wenn ich jetzt erfolgreich ein Element draußen habe und das Array somit eines kürzer ist (19 statt vorher 20), muss ich ja das 20. Element praktisch löschen bzw. freigeben.
Geht einfach
SetLength(Liste, 19);
oder muss da was anderes her?
|
|
Schattengeist
      
Beiträge: 29
|
Verfasst: Sa 10.07.04 18:18
Was ist TDatenRec? Ein Objekt? dann etwas lustiger. Ein Record? Dann einfach die Liste kürzen.
|
|
iX0r
      
Beiträge: 34
Ubuntu
D6, Lazarus
|
Verfasst: Sa 10.07.04 19:51
hier empfiehlt sich als datenstruktur natürlich eine verkette liste.
damit kannst du elemente sehr einfach entfernen, bedingung ist natürlich, daß du dich wein wenig mit pointern auskennst.
mfg
iX0r
|
|
Elite
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 10.07.04 21:11
Mit Hilfe der Suchfunktion und des eigenen gehirns gelöst. ^^
|
|
Tino
      

Beiträge: 9839
Erhaltene Danke: 45
Windows 8.1
Delphi XE4
|
Verfasst: So 11.07.04 09:24
Poste doch mal deine Lösung... würde mich interessieren 
|
|
Elite
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 11.07.04 20:40
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TForm1.DeleteArrayIndex(var X: TListe; Index: Integer); var a:integer; begin if Index > High(X) then exit; if Index < Low(X) then exit; if Index = High(X) then begin SetLength(X, Length(X) - 1); Exit; end; for a:= index to length(X)-2 do X[a]:=X[a+1]; SetLength(X, Length(X) - 1); end;
...
DeleteArrayIndex(Liste, ListBox1.ItemIndex); |
So viel schonmal dazu.
Nun haben sich bei mir allerdings weitere Probleme ergeben. Ich möhte das dynamische Array mit Hilfe eines FileStreams in eine Datei bringen und zwar in folgender Struktur:
Passwort: String;
Length(Liste): Integer;
Und nun die Array-Elemente...
Bei Öffnen werden willkürlich irgendwelche Speicherbereiche ausgelesen wie zB. der Inhalt der Variable "FileName" oder auch Captions einiger Labels. Es folgen die Deklarationen des TDatenRec, des dyn. Array TListe und der Speicher bzw. Öffnen-Code:
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:
| type TDatenRec = Record Titel, LoginName, Passwort, Information: String; end;
type Tliste = array of TDatenRec;
...
procedure TForm1.Speichern; var stream: TFileStream; FileName: string; Laenge:Integer; a:integer; begin FileName:=ExtractFilePath(Application.ExeName) + 'data.dat'; if not fileexists(FileName) then begin stream:= TFilestream.Create(Filename, fmcreate); stream.write(Passwort, SizeOf(Passwort)); a:=0; stream.write(a, SizeOf(integer)); stream.Free; end;
stream:= TFileStream.create(FileName, fmopenwrite); with stream do begin write(passwort, sizeof(passwort)); Seek(sizeOf(string), soFromBeginning); Laenge:=length(Liste); Write(Laenge, SizeOf(laenge)); for a:= 0 to length(Liste)-1 do write(Liste[a], SizeOf(TDatenRec)); Free; end; end;
procedure TForm1.FormCreate(Sender: TObject); var stream: TFileStream; FileName: string; Passwort: string; a:integer; begin Passwort:=''; FileName:=ExtractFilePath(Application.ExeName) + 'data.dat'; If not FileExists(FileNAme) then exit; stream:= TFileStream.create(FileName, fmopenread); with stream do begin Read(Passwort,SizeOf(String)); read(a, sizeOf(integer)); SetLength(Liste,a); for a:= 0 to length(liste)-1 do begin Read(Liste[a],SizeOf(TDatenRec)); ListBox1.Items.Add(Liste[a].Titel); end; end; stream.Free; end; |
Mache ich einen Denk- oder Unwissenheitsfehler?
Ich weiß unterdessen nicht einmal, ob das Problem beim Speichern oder Öffnen der Datei auftritt.
Würde mich über Hilfe sehr freuen!
Wenn jemand nen Screeni oder das Projekt bräuchte, bitte Bescheid sagen.
|
|
obbschtkuche
Gast
Erhaltene Danke: 1
|
Verfasst: So 11.07.04 20:54
|
|
Elite
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 12.07.04 19:13
| obbschtkuche hat folgendes geschrieben: | Delphi-Quelltext 1: 2: 3:
| stream.write(@str[1]^, length(str)); ... stream.read(@str[1]^, length(str)); | |
Also ich habe generell verstanden, wie Zeiger funktionieren. Nur ich verstehe die [1] in den beiden Zeilen nicht. Mit @ die Addresse von Str ermitteln und mit ^ den Speicherbereich auslesen. Aber warum die [1]?
Edit:
Hab eben den Code getestet. Funktioniert nicht so, wie du ihn geschrieben hast.
Aber so geht es:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| foo:=length(str); write(foo,4); write(str[1], length(str)); ... read(foo,4); setLength(str,foo); read(str[1], length(str)); |
Obwohl ich nach wie vor nicht verstehe, was die [1] zu bedeuten hat, funktioniert esnicht ohne sie.
|
|
maximus
      
Beiträge: 896
Win XP, Suse 8.1
Delphi 4/7/8 alles prof
|
Verfasst: Di 13.07.04 09:52
Hi, weil strings auch nur pointer sind und bei [1] fängt der eigentlich string an 
_________________ mfg.
mâximôv
|
|