Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi EIntOverflow bei Generierung von Zeichenketten (https://www.delphipraxis.net/166250-eintoverflow-bei-generierung-von-zeichenketten.html)

luke2 4. Feb 2012 12:38

Delphi-Version: 2007

EIntOverflow bei Generierung von Zeichenketten
 
Hallo!

Ich habe folgenden Testcode um einige Zeichenketten im brute-force-style zu generieren.
Delphi-Quellcode:
var s:string;p:pchar;i:integer;
begin
  s := #97; //#97 = 'a'
  p := pchar(s);
  for i := 1 to 5000 do
  begin
    writeln(s);
    if p^ = #122 then //#122 = 'z'
    begin
      s := s + #97;
      inc(p);
    end
    else
      inc(p^);
  end;
  writeln('ok');
  readln
end.
An diesem Code scheint irgendwas nicht zu stimmen. Von a bis zzza werden alle Zeichenketten korrekt generiert, aber danach ändert sich nichts mehr und irgendwann tritt ein Integerüberlauf in der Zeile inc(p^) auf.
Kann mir jemand sagen was daran falsch ist? Es hat wahrscheinlich etwas mit dem Zeiger (PChar) zu tun, oder?

einbeliebigername 4. Feb 2012 13:46

AW: EIntOverflow bei Generierung von Zeichenketten
 
Hallo,

dass das überhaupt einen String mit zwei Zeichen generiert ist ein Wunder.
Zitat:

Zitat von luke2 (Beitrag 1149183)
Delphi-Quellcode:
      s := s + #97;

An der Stelle wird ein neuer String generiert. P Zeigt aber noch auf den Alten.

Besser so:
Delphi-Quellcode:
var s:string;i:integer;j:integer;
 begin
   s := 'a'; // gleich a reinschreiben, dann kann man sich den Kommentar sparen
   j:= 1;
   for i := 1 to 5000 do
   begin
     writeln(s);
     if s[j] = 'z' then     begin
       s := s + 'a';
       inc(j);
     end
     else
       inc(p[j]); // Achtung: ungetestet
   end;
   writeln('ok');
   readln
 end.
einbeliebigername.

[edit]: himitsu danke, bin wohl noch nicht wach. Fehler
Delphi-Quellcode:
j:= 0;
beseitigt.

himitsu 4. Feb 2012 13:47

AW: EIntOverflow bei Generierung von Zeichenketten
 
Du speicherst nur am Anfang einmal einen Buschtaben in S, host dir davon den Pointer P und veränderst danach ständig das S.

Und nun rate mal, was passiert ... der Speicher von S ändert sich, er liegt nun also an einer anderen Stelle, aber du bleibst hartnäckig auf der alten Position stehen, schreibst somit in der Wildnis rum und verschrottest somit auch fremden Speicher, welche nicht mehr zum S gehört. :roll:


Du mußt also nach Änderung von S auch P aktualisieren, oder laß das unsicher Pointer-Gedöhns.
Delphi-Quellcode:
var
  s: string;
  i, i2: integer;
begin
  s := 'a';
  i2 := 1;
  for i := 1 to 5000 do
  begin
    writeln(s);
    if s[i] = 'z' then
    begin
      s := s + 'a';
      inc(i2);
    end
    else
      inc(s[i2]);
  end;
  writeln('ok');
  readln;
end.
[edit]
@einbeliebigername: Beachte, daß Strings bei 1 und nicht bei 0 beginnen. :wink:

[edit2]
i2/j ist ja das letzte Zeichen, also kann man auch das Letzte verwenden, anstatt mitzuzählen. :angle2:
Delphi-Quellcode:
var
  s: string;
  i: Integer;
begin
  s := 'a';
  for i := 1 to 5000 do
  begin
    WriteLn(s);
    if s[Length(s)] = 'z' then
      s := s + 'a'
    else
      Inc(s[Length(s)]);
  end;
  WriteLn('ok');
  ReadLn;
end.

luke2 4. Feb 2012 14:04

AW: EIntOverflow bei Generierung von Zeichenketten
 
Danke Euch, da habe ich wohl mal wieder Mist gebaut :)

himitsu 4. Feb 2012 14:10

AW: EIntOverflow bei Generierung von Zeichenketten
 
Merk dir einfach Folgendes:
Sobald etwas an der Speicherverwaltung des Strings oder eines dynamischen Arrays verändert wird (z.B. Änderung der Länge), werden Zeiger eventuell ungültig.

Oder Andersrum:
Zeiger sind nur solange gültig, wie an der Speicherverwaltung nicht rumgespielt wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:55 Uhr.

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