Autor Beitrag
Elite
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: 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.

ausblenden 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 user profile iconPeter Lustig: Topic aus VCL (Visual Component Library) verschoben am Sa 10.07.2004 um 12:20
Schattengeist
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 29



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 346



BeitragVerfasst: Sa 10.07.04 12:39 
Moin!

Wieso Objekte? Nimm TList und dann kannste das gleiche auch mit deinen Records machen...

MfG
Muetze1
bms
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 735

Win XP
Delphi 3, Delphi 6 PE, Delphi 2005 PE
BeitragVerfasst: 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.

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 29



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 480

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 29



BeitragVerfasst: Sa 10.07.04 18:18 
Was ist TDatenRec? Ein Objekt? dann etwas lustiger. Ein Record? Dann einfach die Liste kürzen.
iX0r
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 34

Ubuntu
D6, Lazarus
BeitragVerfasst: 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



BeitragVerfasst: Sa 10.07.04 21:11 
Mit Hilfe der Suchfunktion und des eigenen gehirns gelöst. ^^
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: So 11.07.04 09:24 
Poste doch mal deine Lösung... würde mich interessieren :-)
Elite
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 11.07.04 20:40 
ausblenden 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:


ausblenden volle Höhe Delphi-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:
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 erfordert variable
    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); // stream.write erfordert Variable
    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); //Das Öffnen findet bei Programmstart statt
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



BeitragVerfasst: So 11.07.04 20:54 
:? Vermutlich liegts an den Strings.

Versuch deine Strings mal so zu speichern:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
 foo: integer;
...
begin
 foo := length(str);
 stream.write(foo, 4);
 stream.write(@str[1]^, length(str));
end;


Laden dann eben so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
 foo: integer;
...
begin
 stream.read(foo, 4);
 setlength(str, foo);
 stream.read(@str[1]^, length(str));
end;
Elite
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 12.07.04 19:13 
obbschtkuche hat folgendes geschrieben:
ausblenden 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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
foo:=length(str); //Speichern
write(foo,4);
write(str[1], length(str));
...
read(foo,4); //Laden
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 896

Win XP, Suse 8.1
Delphi 4/7/8 alles prof
BeitragVerfasst: Di 13.07.04 09:52 
Hi, weil strings auch nur pointer sind und bei [1] fängt der eigentlich string an :wink:

_________________
mfg.
mâximôv