Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Mehere Elemente eines Feldes löschen durch überschreiben? (https://www.delphipraxis.net/103790-mehere-elemente-eines-feldes-loeschen-durch-ueberschreiben.html)

Lotus 21. Nov 2007 22:26


Mehere Elemente eines Feldes löschen durch überschreiben?
 
Hallo, ich bin gerade dabei mit Arrays zu arbeiten und nun bin ich auf die Sache gestoßen wie man löschen kann. Allerdings soll in meiner Ausgabe (Listbox) ja dann keine freistelle sein, sondern einfach der naechste wert den gelöschten wert ueberschreiben!
Ok hört sich ziemlich seltsam an, ich probiers mal kurz an nem bsp zu erlaeutern:

Index des Feldes : 1 2 3 4 5
Zahl des Feldes : 3 2 4 2 6

Wenn ich jetzt mag das die Zahl 2 gelöscht wird dann würde ja 3 '' 4 '' 6 und ich mag halt das
3 4 6 da steht.. und natuerlich nur die indizies 1-3

geklappt hat dies alles auch wunderbar wenn die zahl nur 1x vorkommt, allerdings sobald es oefter gelöscht werden muss bin ich am scheitern..

bis her sieht meine prozedure so aus


const af=5;


Delphi-Quellcode:
procedure loeschen(var j:integer);
var i:integer; //Zaehlervariable
begin
for i:=j to af-1 do
a[i]:=a[i+1];
a[af]:=0;
dec(af);
end;
j is einfach der Index wo die 2 steht, gesucht wurde diese stelle durch eine lineare suche...

so das war jetzt fuer 1 element löschen und nun hab ich das so geschrieben fuer mehere

Delphi-Quellcode:
procedure var1(var a:ta; var af:integer; key:te);
var i,temp,afneu:integer;
begin
afneu:=af;
temp:=0;
for i:=1 to af do
if uppercase(a[i]) = uppercase(key) then begin
for temp:=i to af do
  a[temp]:=a[temp+1];
  a[afneu]:=' ';
  dec(afneu);
  end
funzt aber nicht, könntet ihr mir vllt verraten wie das geht?
aber bitte sagt mir nicht das ich einfach ne andere art von löschen benutzen soll, andere varianten habe ich schon, ich brauch halt nur noch diese

LoCrux 22. Nov 2007 00:53

Re: Mehere Elemente eines Feldes löschen durch überschreiben
 
Hi Lotus,

vielleicht hilft es Dir:

Delphi-Quellcode:
type
  TCharArray = array of Char;
  TByteArray = array of Byte;

function Kill(const Kill:Char;const StrArr:TCharArray):TCharArray;
var
  i,Count       : Word;
  ToKill        : Byte;
  tempByteArr   : TByteArray absolute StrArr;
begin
  ToKill := ORD(Kill);
  Count := 0;
  for i := Low(StrArr) to High(StrArr)
  do begin
    if (tempByteArr[i]<>ToKill)
    then begin
      INC(Count);
      SetLength(result,Count);
      result[count-1] := StrArr[i];
    end;
  end;
end;

function KillAndFill(const Kill,Fill:Char;const StrArr:TCharArray):TCharArray;
var
  i          : Word;
  ToKill     : Byte;
  tempByteArr : TByteArray absolute StrArr;
begin
  ToKill := ORD(Kill);
  SetLength(result,High(StrArr)+1);
  for i := Low(StrArr) to High(StrArr)
  do begin
    if (tempByteArr[i]<>ToKill)
    then result[i] := StrArr[i]
    else result[i] := Fill;
  end;
end;
Frage vorweggenommen:

tempByteArr : TByteArray absolute StrArr zeigt auf den gleichen Bereich im Speicher, wie auch const StrArr:TCharArray. Die vergleichsoperation (tempByteArr[i]<>ToKill) wird vom Compiler (da jetzt ein definierter Byte-Vergleich) viel effizenter umgesetzt. Kann bei vielen aufrufen der Funktion von Vorteil sein.

Kill : Loescht und gibt ein kuerzeres Array zurueck.
KillAndFill : Ersetzt.

Amateurprofi 22. Nov 2007 02:57

Re: Mehere Elemente eines Feldes löschen durch überschreiben
 
@LoCrux:

Ich würde KILL so aufbauen :

Delphi-Quellcode:
PROCEDURE xKill(kill:char; var StrArr:TCharArray);
var i,j:integer;
begin
   j:=0;
   for i:=0 to High(StrArr) do
      if StrArr[i]<>kill then begin
         StrArr[j]:=StrArr[i];
         inc(j);
      end;
   SetLength(StrArr,j);
end;
Warum ?:
Weil bei deiner Version SetLength wiederholt aufgerufen wird, nämlich für jeden Char, der nicht gelöscht wird.
Bei XKill nur einmal!
Bei Length(StrArr) = 10 habe ich gemessen
Für deine Version 4584 CPU-Ticks
Für meine Version 548 CPU-Ticks
Die Vervendung von Byte statt Char bringt meines Erachtens nichts, denn Char und Byte werden identisch abgewickelt.

Und zum Nachprüfen die Prozedur, mit der ich das getestet habe.

Delphi-Quellcode:
PROCEDURE TMain.Test;
var ta:TCharArray; i,n:integer; t0,t1,t2:Int64; s1,s2:string;

FUNCTION TimeStamp:Int64;
asm
   rdtsc;
end;

begin
   t1:=High(int64);
   t2:=High(int64);
   for n:=1 to 10 do begin
      // Ticks für KILL messen
      setlength(ta,10);
      for i:=0 to 9 do ta[i]:=Chr(Ord('a')+i);
      t0:=TimeStamp;
      ta:=Kill('c',ta);
      t0:=TimeStamp-t0;
      if t0<t1 then t1:=t0;
      s1:='';                              // Nur zur Kontrolle, ob die
      for i:=0 to high(ta) do s1:=s1+ta[i]; // Ergebnisse idenstisch sind
      // Ticks für xKILL messen
      setlength(ta,10);
      for i:=0 to 9 do ta[i]:=Chr(Ord('a')+i);
      t0:=TimeStamp;
      xKill('c',ta);
      t0:=TimeStamp-t0;
      if t0<t2 then t2:=t0;
      s2:='';                              // Nur zur Kontrolle, ob die
      for i:=0 to high(ta) do s2:=s2+ta[i]; // Ergebnisse idenstisch sind
   end;
   showmessage(s1+' '+IntToStr(t1)+#13+s2+' '+IntToStr(t2));
end;

LoCrux 22. Nov 2007 06:33

Re: Mehere Elemente eines Feldes löschen durch überschreiben
 
@Amateurprofi

OK! Keine Einwaende (war ja auch nur Qick'N'Dirty direkt reingetippt).

Zitat:

Die Vervendung von Byte statt Char bringt meines Erachtens nichts, denn Char und Byte werden identisch abgewickelt.
Ich hab da, so dunkel in einer Gehirnwindung (dicht unterhalb der rechten Geheimratsecke), noch im Sinn
dass ich mal auf 'ner CodeGear-Seite was darueber gelesen hab. Ging da glaub um Suchen nach bestimmten Patterns
in grossen Textdateien.

Dann aendern wir aber auch

Delphi-Quellcode:
procedure KillAndFill(const Kill,Fill:Char;var StrArr:TCharArray);
var
  i          : Integer;
begin
  for i := 0 to High(StrArr)
      do if (StrArr[i]=Kill) then StrArr[i] := Fill;
end;

Lotus 22. Nov 2007 11:23

Re: Mehere Elemente eines Feldes löschen durch überschreiben
 
also erstmal danke euch beiden für die schnelle antworten, allerdings muss ich sagen das ich noch "relativ" neu bin und wir leider in der schule nicht wirklich irgendwie solch einen quelltext schreiben, dieses ganze TCharArray und StrARR oder so damit komm ich irgendwie noch nich ganz so klar

Delphi-Quellcode:
PROCEDURE xKill(kill:char; var StrArr:TCharArray);
var i,j:integer;
begin
   j:=0;
   for i:=0 to High(StrArr) do
      if StrArr[i]<>kill then begin
         StrArr[j]:=StrArr[i];
         inc(j);
      end;
   SetLength(StrArr,j);
end;
das versteh ich aber schon einigermaßen und ich werds mal so probieren..

LoCrux 23. Nov 2007 00:36

Re: Mehere Elemente eines Feldes löschen durch überschreiben
 
@Lotus

Zitat:

dieses ganze TCharArray und StrARR oder so damit komm ich irgendwie noch nich ganz so klar
Ist eigentlich ganz einfach. Wenn eine Variable deklariert wird, muss ihr auch ein Typ zugewiesen werden (Real,Integer, Word, String, etc). In (fast) allen Hochsprachen, wie z.B. Delphi, kann man sich solche Typen auch selber definieren.

Du kannst z.b. scheiben:

Delphi-Quellcode:
TMyInteger = Integer;
Damit wird jede Variable vom Typ TMyInteger zum einem Integer-Typen. Analog geht das mit Arrays.

Wenn Du eine Variable EineMenge : Array[0..10] of Char; deklariest, kannst Du vorher auch einen einen Typ TEineStatischeMenge : Array[0..10] of Char; definieren und dann "sagen" EineStatischeMenge : TEineStatischeMenge;.
Den Typ TEineStatischeMenge, nennt man ein statisches Array, da immer Speicherplatz fuer genau 11 !! Elemente (0..10) bereitstellt (reserviert).

Wenn Du allerdings vorher nich genau weisst, wie gross Deine Menge sein soll oder wird, geht analog dazu TEineDynamischeMenge : Array of Char;. Deine Variable koennte dann EineDynamischesMenge:TEineDynamischeMenge heissen.
Wie oben: Den Typ TEineDynamischeMenge, nennt man ein dynamisches Array, da die Anzahl (der belegte Speicher) deiner Elemente dynamisch (deinen wuenschen entsprechend) vergoessert oder verkleinert werden kann.
Das geht mit SetLength(EineDynamischeMenge,11); (Setze die Laenge von Variablenname auf 11 Elemente).

Noch was zur Konvention (ungeschiebenes Gesetz). Eigene Typen sollte immer der Buchstaben T fuer Type
vorangestellt werden, da dann andere Programmierer (auch wenn sie nur einen Auszug aus deinem Programm sehen) sofort
wissen: "Ahhhh.. hier hat Er einen neuen Typen eigefuehrt."
Natuerlich solltest Du dann auch die Typendeklaration mit angeben oder sog. Self-Explaining-Type-Declarations (Seblstbeschreibende Deklaration) verwenden.
z.B. TArrayOf10Integers oder TDynArrayOfString.

Hoffe, hat geholfen (falls Dich ein Lehrer ausquetscht).

Lotus 23. Nov 2007 08:00

Re: Mehere Elemente eines Feldes löschen durch überschreiben
 
jaaa auf jedenfall.. vielen vielen dank das war wirklich sehr gut erklärt.. dann werd ich mir den quellcode nochmal genauer unter die lupe nehmen ;) thx!!!


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz