Dynamiczna tablica źle działa

0

Zadeklarowałem dynamiczną tablicę i stopniowo zwiększając jej długość dodawałem elementy:

implementation
var Ob:byte; //do zwiększania długości tablicy w razie wykrycia szukanego znaku (tutaj spacji)
PauArr:array of integer; //tablica dynamiczna
TL:String;

procedure SzukSpacji;
var i:byte;
begin
for i := 1 to Length(TL) do
    if TL[i]=' ' then

       begin
            Ob:=Ob+1;
            SetLength(PauArr,Ob);
            PauArr[Ob]:=i;

            ShowMessage(IntToStr(PauArr[Ob]));// pokazuje że rzeczywiście wartość została dodana do tablicy
        end;
end;

Rzeczywiście mam potwierdzenie że elementy są dodawane do tablicy prawidłowo: (ShowMessage(IntToStr(PauArr[Ob])); )
Ale.. jeżeli chcę dostać się do tablicy z innej procedury:

procedure SprawdzTablice;
var n:byte;
begin
      For n:=1 to Length(PauArr) do
      ShowMessage(IntToStr(PauArr[n]));
end;

To okazuje się że wszystkie elementy tablicy dynamicznej mają wartość zero (0).
Sprawdzałem dokładnie to samo ale ze zwykłą (niedynamiczną) jednowymiarową tablicą
(PArr: array[1..20] of integer;) i wówczas wszystko jest dobrze to znaczy można pobierać prawidłowe wartości tablicy z innych procedur niż ta w której tablica była wypełniana.
Co jest przyczyną że moja tablica dynamiczna zachowuje się nieprawidłowo (traci dodane wartości)?

1

Mhm… a od kiedy to dynamiczne macierze indeksowane są od 1? Ten kod powinien rzucać wyjątkami na lewo i prawo, ale widać range checking masz wyłączony, dlatego nie wiesz nic o tym co się dzieje.

W procedurze SzukSpacji, po spełnieniu warunku ciągle odwołujesz się do elementu o jeden za daleko, czyli de facto poza mecierzą (o ile przed wywołaniem tej procedury zmienna Ob zostaje zainicjowana zerem). Ciągle mażesz po pamięci za tablicą, więc słusznie masz w niej same zera (SetLength zeruje dodatkowy obszar, jeśli zwiększa rozmiar tablicy). Drugi błąd to iterowanie po elementach macierzy znów od 1 zamiast od 0 w procedurze SprawdzTablice.

Czas wziąć do ręki kurs z podstawami programowania w Delphi, bo masz potworne braki. Oprócz błędnego indeksowania pętli, widać jeszcze nie znasz funkcji Length i High, ani też pętli for in.


Przykładowy kod testowej aplikacji konsolowej:

type
  TSpaceIndices = array of Integer;

  procedure FindSpaces(const AValue: String; out AIndices: TSpaceIndices);
  var
    I: Integer;
  begin
    SetLength(AIndices, 0);

    for I := 1 to Length(AValue) do
      if AValue[I] = ' ' then
      begin
        SetLength(AIndices, Length(AIndices) + 1);
        AIndices[High(AIndices)] := I;
      end;
  end;

  procedure CheckIndices(const AIndices: TSpaceIndices);
  var
    I: Integer;
  begin
    for I in AIndices do
      Write(I:3);
  end;

var
  Value: String = 'one two three  ';
  Indices: TSpaceIndices;
begin
  FindSpaces(Value, Indices);
  CheckIndices(Indices);
end.

Na wyjściu otrzymamy:

  4  8 14 15

1 użytkowników online, w tym zalogowanych: 0, gości: 1