Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Zugriffsverletzung bei Schleife (https://www.delphipraxis.net/132623-zugriffsverletzung-bei-schleife.html)

Dragon27 16. Apr 2009 10:17


Zugriffsverletzung bei Schleife
 
Hallo zusammen,

ich sitze nun schon eine Ewigkeit an einem Problem. ICh habe folgenden Code:

Delphi-Quellcode:
function Extract(Text : string; WordPos : Word): string;
var
p : PChar;
begin
  p := PChar(Text);
  repeat
    Dec(WordPos);
    while p^ <> ':' do
    begin
      if WordPos = 0 then
       Result := Result + p^;
      Inc(p);
    end;
    if WordPos = 0 then Exit;
    Inc(p);
  until p^ = ':';
end;

procedure TForm5.BitBtn1Click(Sender: TObject);
var
  Datei,Ziel:PChar;
  i:integer;
begin
  try
    if radiobutton1.Checked then begin
    Datei := pchar('http://lyricwiki.org/api.php?func=getSong&artist='+Edit1.Text+'&song='+edit2.Text+'&fmt=text');
    end;
    if radiobutton2.Checked then begin
    Datei := pchar('http://lyricwiki.org/api.php?func=getSong&artist='+Edit1.Text+'&song=&fmt=text');
    end;
      Ziel := pchar(extractfilepath(paramstr(0))+'List.txt');
      UrlDownloadToFile(nil, Datei, Ziel, 0, nil);
      Listbox1.Items.LoadFromFile(extractfilepath(paramstr(0))+'List.txt');
      Combobox1.clear;
    for I := 0 to Listbox1.items.Count - 1 do begin
       Combobox1.items.add(extract(Listbox1.Items[i],2)); // FEHLER nach einem Durchlauf
    end;
  except
    showmessage('Download abgebrochen');
  end;

end;
Dieser Code solleigentlich nichts anderes machen, als eine Ergebnisliste im *.txt Format auswerten. Die Ergebnisse
haben immer das Format Interpret:Titel. Ich möchte jetzt nur die Titel haben und verwende deswegen die Function Extract.
Leide ist genau bei dieser Schleife immer eine Zugriffsverletzung das Ergebnis. In der Combobox steht dann nur 1 Item.

Kann mir jemand sagen was ich falsch gemacht habe?

Danke!

nahpets 16. Apr 2009 10:30

Re: Zugriffsverletzung bei Schleife
 
Hallo,

wie wäre es denn damit?
Delphi-Quellcode:
Combobox1.items.add(Copy(Listbox1.Items[i],Pos(':',Listbox1.Items[i]) + 1,Length(Listbox1.Items[i])));
Alles hinter dem ersten Doppelpunkt holen.

Dragon27 16. Apr 2009 10:32

Re: Zugriffsverletzung bei Schleife
 
Danke, dein Vorschlag funktioniert prächtig ;-)

Kannst du mir bitte erklären was bei meiner Version falsch war?

Danke!

GroHae 16. Apr 2009 10:40

Re: Zugriffsverletzung bei Schleife
 
Hi

ich habe deinen Code mit

ShowMessage(Extract('Hallo : Thomas',2));

getestet.

Das Ergebnis ist dann ein Zufallswert: Thomas + 'irgendetwas' da die Abbruchsbedingung bei

Delphi-Quellcode:
    while p^ <> ':' do
    begin
      if WordPos = 0 then
       Result := Result + p^;
      Inc(p);
    end;
fehlt. Debug das mal dann siehst du es.

Wenn ich
ShowMessage(Extract('Hallo : Thomas:,2)); // ':' Ans Ende angefügt
sage klappts.

Ich vermute das ist die Ursache

nahpets 16. Apr 2009 10:44

Re: Zugriffsverletzung bei Schleife
 
Hallo,
Zitat:

Zitat von Dragon27
Danke, dein Vorschlag funktioniert prächtig ;-)

Kannst du mir bitte erklären was bei meiner Version falsch war?

Danke!

nein kann ich nicht, weil ich auf die Schnelle da nicht durchgestiegen bin ;-), hab' gedacht, machste einfach 'ne andere Lösung.

Irgendwie machst Du aus einem String 'nen PChar und beginnst immer mit der 2. Position, die Du dann per Dec auf die erste Position setzt. Nun gehst Du zeichenweise durch den PChar um den : zu suchen. Wenn WordPos = 0, wird Result um p^ erhöht
und dann wird p erhöht, bis p^ = : ist. Dann wird p^ erhöht und solange weitergemacht, bis p^ = : ist. Das sieht mir so aus, als würde das jetzt weitergehen, bis der 2. Doppelpunkt gefunden wird, es sei denn WordPos wird vorher 0.
Irgendwie verstehe ich das nicht so recht.

GroHae 16. Apr 2009 10:55

Re: Zugriffsverletzung bei Schleife
 
Zitat:

Irgendwie machst Du aus einem String 'nen PChar und beginnst immer mit der 2. Position, die Du dann per Dec auf die erste Position setzt. Nun gehst Du zeichenweise durch den PChar um den : zu suchen. Wenn WordPos = 0, wird Result um p^ erhöht
und dann wird p erhöht, bis p^ = : ist. Dann wird p^ erhöht und solange weitergemacht, bis p^ = : ist. Das sieht mir so aus, als würde das jetzt weitergehen, bis der 2. Doppelpunkt gefunden wird, es sei denn WordPos wird vorher 0.
Irgendwie verstehe ich das nicht so recht.
Stimmt mir geht's ähnlich.

wie das mit
Delphi-Quellcode:
    Inc(p);
geht ist mir nicht klar



Aus meiner Toosammlung:

Delphi-Quellcode:
function GetTeilString(S: string; Pos: integer; Trenner: string; TrimAll:boolean=false): string;
var
  i, j: integer;
  S2: string;
begin
  j := 0;
  S2 := '';
  if S <> '' then
  begin
    if S[Length(S)] <> Trenner then
      S := S + Trenner;
    // 31.03.2009: Noch ein Sicherheitsabfang
    S := S + ' ' + Trenner;
    { Beginn suchen }
    for i := 1 to (pos - 1) do
    begin
      j := j + 1;
      while s[j] <> Trenner do
        j := J + 1
    end;
    { Wert setzen }
    j := j + 1;
    while s[j] <> Trenner do
    begin
      S2 := S2 + S[j];
      j := J + 1
    end;
  end;
  Result := TrimRight(S2);
  if TrimAll then
    Result := Trim(S2);
end;
nicht so elegant wie deine Lösung, aber ich arbeite nicht gerne mit PChar und ^

nahpets 16. Apr 2009 11:01

Re: Zugriffsverletzung bei Schleife
 
Hallo,

per For-Schleife über 'nen String finde ich irgendwie schön einfach, jenachdem, was man macht, ist das einfacher und auch schneller, als mit Pos und PosEx und ggfls. zwischendurch noch Teilstrings erstellen.

Blup 16. Apr 2009 11:03

Re: Zugriffsverletzung bei Schleife
 
Delphi-Quellcode:
p := PChar(Text);
Bei einem leeren Text '' ist p an dieser Stelle nil.
Jeder Zugriff auf p^ würde jetzt zu einer Zugriffsverletzung führen.

In deinen Schleifen wird nie überprüft ob das Ende des Textes erreicht wurde (z.B. p^ = #0).
Dann müsste abgebrochen werden.

Delphi-Quellcode:
...
    Inc(p);
  until p^ = ':';
Diese Stelle wird nur erreicht wenn p^ = ':' ist.
Durch Inc(P) ist die nachfolgende Bedingung nie erfüllt, es sei denn, es stehen zwei Doppelpunkte nacheinander.


Delphi-Quellcode:
function Extract(Text: string; WordPos: Word): string;
var
  p: PChar;
begin
  p := PChar(Text);
  if Assigned(p) then
  begin
    while (p^ <> #0) and (WordPos > 0) do
    begin
      if p^ = ':' then
        Dec(WordPos)
      else if WordPos = 1 then
        Result := Result + p^;
     
      Inc(p);
    end;
  end;
end;
Na da war jemand bereits schneller... :wink:


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:38 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