Autor |
Beitrag |
Georg08
      
Beiträge: 155
Erhaltene Danke: 6
Win XP
Delphi 7.0 Personal
|
Verfasst: Di 30.11.10 20:25
Hallo Community,
ich habe ein Programm geschreiben, dass ein dynamisches Array besitzt, und in dises Array auch gut schreiben kann. Auch das Auslesen funktioniert reibungslos, aber wenn ich versuche ein Element zu löschen bekomme ich ein paar probleme
Ich habe gegoogelt und hier einen Artikel gefunden. Diesen habe ich dann auf mein Programm angewandt. Aber mein Problem ist, dass wenn ich bestimmte Elemente lösche irgenwas nicht mehr stimmt.
Die ersten paar Einträge (Einträge "weit vorne" wie Array[2]) kann ich ohne Probleme löschen, aber wenn ich versuche z.B. den vorletzen Eintrag zu löschen werden mir in meinem StringGrid (in das ich die Werte zuzeit noch auslese) beim "neuen" letzen Eintrag seltsame Zeichen angezeigt. Den letzen Eintrag jedoch kann ich wieder problemlos löschen...
Das Array ist als eine von mir ein angelegte Klasse definiert.
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:
| [...] type TBenutzer = record Name: String; Nachname: String; end; [...] type TKartei = class private Benutzer: Array of TBenutzer public USerCount: Integer; [...] procedure Delete(Index: Integer); [...] procedure TKartei.Delete(Index: Integer); begin if Index < UserCount then begin Move(Benutzer[Index+1], Benutzer[Index], (Length(Benutzer)-Index-1)); SetLength(Benutzer, Length(Benutzer)-1); dec(UserCount); end else raise Exception.CreateFmt('Fehler! Eingabe ''%d'' überschreitet Maximum ''%d''', [KartenIndex, KartenCount]); end; |
Original vom Link oben:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| procedure DeleteArrayElement(var AArray: TIntArray; const AIndex: Integer); var i: Integer; begin Move(AArray[AIndex + 1], AArray[AIndex], SizeOf(AArray[0]) * (Length(AArray) - AIndex - 1)); SetLength(AArray, Length(AArray) - 1); end; |
|
|
Jakob_Ullmann
      
Beiträge: 1747
Erhaltene Danke: 15
Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
|
Verfasst: Di 30.11.10 20:34
Vielleicht hilft es, Name als string[...] mit festgelegter Zeichenanzahl zu deklarieren?
Zumindest muss da am Ende irgendwas sein, was noch mit eingelesen wird, aber kein String ist (könnte ich mir vorstellen, vor allem mit Lazarus hatte ich in letzter Zeit solche Probleme).
EDIT: Jedenfalls glaube ich nicht, dass Move etwas anderes als memmove() macht (auch, wenn ich es noch nie verwendet habe). Vor allem, wenn man die Deklaration anschaut:
Quelltext 1:
| void *memmove(void *dest, const void *src, size_t n); |
Zuletzt bearbeitet von Jakob_Ullmann am Di 30.11.10 20:41, insgesamt 2-mal bearbeitet
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 30.11.10 20:38
Gibt es einen Grund, dass du keine Liste benutzt?
Ab Delphi 2009 kannst du mit Generics sogar direkt eine Liste mit dem konkreten Typ erstellen.
Am einfachsten geht das natürlich, wenn du statt des Records eine Klasse benutzt. Dann musst du nicht umständlich selbst mit Pointern spielen, sondern hast direkt welche. Das gilt auch für deine jetzige Situation.
Was durch das Move vermutlich passiert ist, dass die Referenzzählung der Strings durcheinanderkommt. Und dadurch werden die Strings evtl. schon zu früh freigegeben oder sowas. Was genau passiert, müsste ich mir anschauen, aber es gibt wie gesagt deutlich einfachere Lösungen.
|
|
Georg08 
      
Beiträge: 155
Erhaltene Danke: 6
Win XP
Delphi 7.0 Personal
|
Verfasst: Di 30.11.10 20:43
Ich habe leider nur Delphi7 PE...
Das mit den Listen naja...
Ich persönlich mag Listen nicht so, besonders wenn man mehrere Werte speichern muss, wie in meinem Beispiel "Name" und "Nachname"
oder wie meinst du das jetzt?
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Di 30.11.10 20:49
Hallo,
fehlt der Groessenberechnung nicht etwas?
Delphi-Quelltext 1:
| Move(Benutzer[Index+1], Benutzer[Index], SIZEOF[Benutzer)*(Length(Benutzer)-Index-1)); |
Natuerlich muesste man selbst vorher die Strings löschen
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TKartei.Delete(Index: Integer); begin if Index < UserCount then begin With Benutzer[Index] do Name := ''; Nachname := ''; end; IF (Index+1)< UserCount then Move(Benutzer[Index+1], Benutzer[Index], SIZEOF[TBenutzer) *(Length(Benutzer)-Index-1)); SetLength(Benutzer, Length(Benutzer)-1); dec(UserCount); end else raise Exception.CreateFmt('Fehler! Eingabe ''%d'' überschreitet Maximum ''%d''', [KartenIndex, KartenCount]); end; |
Gruß Horst
|
|
bummi
      
Beiträge: 1248
Erhaltene Danke: 187
XP - Server 2008R2
D2 - Delphi XE
|
Verfasst: Di 30.11.10 20:55
Ich würde von dem fehlerträchtigen UserCount absehen und statt dessen
High(Benutzer) + 1 nehmen und beim Löschen das Array redimensionieren, beim Einfügen tust Du dies ja (wahrscheinlich) eh schon.
_________________ Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 30.11.10 21:37
Georg08 hat folgendes geschrieben : | Ich persönlich mag Listen nicht so, besonders wenn man mehrere Werte speichern muss, wie in meinem Beispiel "Name" und "Nachname" |
Genau dafür ist es doch ideal.
Beispiel: 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:
| type TUserInfo = class private FFirstName: string; FLastName: string; public property FirstName: string read FFirstName write FFirstName; property LastName: string read FLastName write FLastName; end;
TForm272 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); private FUserList: TObjectList; public end;
var Form272: TForm272;
implementation
{$R *.dfm}
procedure TForm272.Button1Click(Sender: TObject); var NewUser: TUserInfo; begin NewUser := TUserInfo.Create; NewUser.FirstName := 'Thomas'; NewUser.LastName := 'Mustermann'; FUserList.Add(NewUser);
NewUser := TUserInfo.Create; NewUser.FirstName := 'Miriam'; NewUser.LastName := 'Musterfrau'; FUserList.Add(NewUser);
FUserList.Delete(0);
ShowMessage(TUserInfo(FUserList[0]).FirstName + ' ' + TUserInfo(FUserList[0]).LastName); end;
procedure TForm272.FormCreate(Sender: TObject); begin FUserList := TObjectList.Create(True); end;
procedure TForm272.FormDestroy(Sender: TObject); begin FUserList.Free; end; |
|
|
Georg08 
      
Beiträge: 155
Erhaltene Danke: 6
Win XP
Delphi 7.0 Personal
|
Verfasst: Di 30.11.10 21:45
Danke
ich denke ich wers jetzt so machen wie jaenicke beschrieben hat. (Danke jaenicke)
Hat übrigens jetzt geklappt, wenn ich beim record dem String eine feste länge gegeben habe... (Danke Jakob_Ullmann)
|
|
|