lokalna tablica dynamiczna jako parametr funkcji

0

Mam taki problem.
Mam dwie procedury, w jednej z nich tworzę dynamicznie tablicę wskaźników do rekordu,
i przekazuję jako parametr do drugiej procedury, która w pętli (rekurencja) wypełnia ją zawartością.

Problem w tym , że niby wszystko działa, ale po wyjściu z procedury wartości znikają :(
Podejrzewam że można to zrobić prościej niż ja, ale potrzebuję podpowiedzi.

Generalnie chodzi o to, że przekazuję do procedury wskaźnik do tablicy oraz string ze zmiennymi, a procedurka ma wydzielić poszczególne składniki i wypełnić tablicę wartościami.

Przykład:
Z czegoś takiego :
'cos1,cos2,cos2';
chcę uzyskać :
T[1]^.nazwaskl='cos1';
T[2]^.nazwaskl='cos2';
T[3]^.nazwaskl='cos3';

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  PrecPodstawka = ^TrecPodstawka;
  TrecPodstawka = record
    Rok      : Integer;
    Miesiac  : Integer;
    NzwSklad : string;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure TablicaArrPodstaw(C:Pointer;Params:string);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  Parametry : string;
  ArrSkl : array of PrecPodstawka;
  i,j : Integer;
begin
     // Przykładowe parametry
     Parametry := 'cos1,cos2,cos3';
     TablicaArrPodstaw(ArrSkl,Parametry);  // WYWOŁANIE 2 PROCEDURY

     Application.MessageBox(pchar('Ilość parametrów : ' + IntToStr(length(ArrSkl))),'test',MB_ICONINFORMATION); //   TU jest 0 a powinno być 3 !!!

end;

procedure TForm1.TablicaArrPodstaw(C: Pointer; Params: string);
var
  i,k : Integer;
  p : Integer;
  S : string;
  T : array of PrecPodstawka;
begin
  S := trim(Params);    // na wszelki wypadek pozbywam się spacji
  T := C;               // przypisanie do tablicy T wskaźnika podanego jako parametr wywołania
  i := length(T);       // sprawdzenie ilości elementów tablicy
  k := length(S);       // sprawdzenie długości stringu Params
  p := Pos(',',S);      // określenie pozycji separatora (przecinek jest separatorem)

  if (k<1) then Exit;   //jeżeli ciąg zanków jest pusty to exit
  if (p=1) then Exit;   //jeżeli na pierwszej pozycji znajduje się przecinek to exit
  if (P=0) then begin   // jeżeli nie znaleziono separatora więc podano tylko jeden składnik - fragment wywołuje się w ostatnim obrocie pętli
    SetLength(T,i+1);
    new(T[i]);
    T[i]^.NzwSklad := S;
  end else begin
    SetLength(T,i+1);   // zwiększenie ilości elementów tablicy
    new(T[i]);          //  utworzenie nowego wskaźnika
    T[i]^.NzwSklad := copy(S,1,p-1);  // podpisanie odczytanego wyrazu do wskaźnika "cos1"
    S := copy(S,p+1,k-(p));   // odcięcie ze stringu pierwszego wyrazu i przecinka(separatora) aby zostało "cos2,cos3"
                              // tutaj jest OK, tablica się powiększa
    TablicaArrPodstaw(T,S);   //<- wywołanie w pętli samej siebie
                              //ale tu, po wyjściu okazuje się że wartość jest nil, a właściwie wartość z przed wywołania
  end;
end;

end.

Czy ktoś podpowie jak to lepiej zrobić lub gdzie robię błąd ?

0
procedure TForm1.Button1Click(Sender: TObject);
var
  Parametry : string;
  SL : TStringList;
begin
     // Przykładowe parametry
     Parametry := 'cos1,cos2,cos3';
SL := TStringList.Create;
try
SL.CommaText := Parametry;

     Application.MessageBox(pchar('Ilość parametrów : ' + IntToStr(SL.Count)),'test',MB_ICONINFORMATION); 
finally
SL.Free;
end;

end;
0

Nie chodzi mi o proste policzenie tylko o przepisanie tego do tablicy rekordów, na której później będę jeszcze przeprowadzał dalsze operacje.

0

pewnie problem bierze się z

    SetLength(T,i+1);   // zwiekszenie ilosci elementów tablicy

tu adres tablicy może się zmienić i informacja ta nie jest przekazywana na zewnatrz procedury

spróbuj tak: stwórz typ w rodzaju

type
  TArrOfPodstawka=array of PrecPodstawka;

i zmodyfikuj kod procedury żeby zamiast przekazywać wskaźnik do tablicy przekazywać całą tablicę przez referencję, czyli procedura będzie zadeklarowana

    procedure TablicaArrPodstaw(var T: TArrOfPodstawka; Params: string);

powinno działać

0

Moim zdaniem musisz i zadeklarowac jako globalne i powinno pomoc :)
Jesli nadal nic sie nie zmieni sprobuj wszystkie zmienne ktore masz dodane w procedurze zadeklarowac globalnie i potem je odrzucaj kolejno do momentu az przestanie dzialac. Moim zdaniem tu bedzie sie chował bug. Wybacz ze nie daje rozwiazania wprost ale nie mam czasu tego wrzucic i sprawdzic w chwili obecnej.

0

Zapytałeś "Czy ktoś podpowie jak to lepiej zrobić" więc dostałeś odpowiedź, więc o co kaman kolo !?

Poza tym jak chcesz na tych danych operować to tym bardziej moja podpowiedź Ci się przyda. Dostęp do poszczególnych elementów jest prosty jak budowa cepa:

ShowMessage(SL[0]);
ShowMessage(SL[1]);
ShowMessage(SL[2]);...

0
tuNadlatujoncyQbek napisał(a)
type
  TArrOfPodstawka=array of PrecPodstawka;

Zgadza się zadziałało. Dzięki za pomoc.

adydan napisał(a)

Moim zdaniem musisz i zadeklarowac jako globalne

Tego chciałem uniknąć aby procedurka był bardziej elastyczna, ale dzięki za odzew.

b0bik napisał(a)

Zapytałeś "Czy ktoś podpowie jak to lepiej zrobić" więc dostałeś odpowiedź, więc o co kaman kolo !?

Faktycznie Twoje rozwiązanie jest bardzo dobre, i załatwia wiele spraw. Już widzę że je wykorzystam w wielu miejscach w kodzie.
Chodziło mi o to, żeby to jednak były rekordy, bo po zakończeniu działania procedurki, przelatuję tablicę od 0 do length(tablica) i uzupełniam wartości dla poszczególnych parametrów, i przetrzymuje te wartości od razu w rekordzie z tym parametrem, a potem przekazuję tą tablicę dalej do wydruku.
A chciałem całość załatwić w jednej procedurze, choć myślę że Twoim sposobem też dałoby się to jakoś zrobić.
Dzięki za pomoc.

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