Umieszczenie całej tablicy w liście

0

Witam,
czy istnieje możliwość zapisu do listy całej tablicy.

Dla przykładu


 type
 listaprzykladow = ^Tlistaprzykladow;
 Tlistaprzykladow = record
   Next: listaprzykladow; 
   tab:array of double;
 end;
.
.
.
public
   poczatek_list:listaprzykladow;
   nastepny:listaprzykladow;

procedure TForm1.FormClick(Sender: TObject);
var TabLista:listaprzykladow;
     example: array of double;
begin
poczatek_list := nil;
nastepny := nil;

example[0]:=1
example[1]:=2
example[2]:=3

New(TabLista);
TabLista^.Next := nil;
TabLista^.tab := example;  // Tutaj miałaby się znajdować tablica z powyższymi danymi
end;
 

Proszę o pomoc.

0

tak, tylko że nie widzę przyczyny czemu nie zrobić zamiast tego zwyczajnie: type listaprzykladow = array of array of double;

0

A Jakby to miało wyglądać ?

0

No właśnie tak jak napisałem.

0

Co chcesz osiągnąć? Jeśli chcesz mieć tą swoją listę, której wartościami poszczególnych elementów listy są dynamiczne tablice double to w zasadzie sam sobie odpowiedziałeś, musisz tylko nadać rozmiar (przydzielić pamięć) tej tablicy przed jej użyciem - służy do tego procedura SetLength . Jeśli natomiast chcesz wywalić tą listę na rzecz tablicy tablic double to tak jak pisał @_13th_Dragon

0

@szopenfx
Chcę mieć listę, której wartościami poszczególnych elementów listy są dynamiczne tablice double.

Ustawiam

setlength(TabLista^.tab,25); 

lecz przy kompilacji otrzymuję błąd w lini
TabLista^.tab := example;
o treści
e2008 incompatible types

1

Utwórz nowy typ TDynDoubleArray = array of double; a później korzystaj z niego zamiast array of double

0

Czemu nie użyć prostych rzeczy przynajmniej dopóki nawet z tablicami masz problem:

type listaprzykladow=array of array of double;

var Tab:listaprzykladow;
var I,L:Integer;
begin
  for I:=0 to 9 do
  begin
    L:=Length(Tab);
    SetLength(Tab,L+1);
    SetLength(Tab[L],10+I);
  end;
  for I:=0 to Length(Tab)-1 do
  begin
    WriteLn(Length(Tab[I]));
  end;
end.
2
lukasz_p92 napisał(a)

lecz przy kompilacji otrzymuję błąd w lini

TabLista^.tab := example;

Jak widać nie możesz w ten sposób kopiować macierzy - musisz najpierw ustalić rozmiar macierzy wyjściowej i skopiować tyle pamięci, ile zajmuje macierz wejściowa; Do obliczenia ilości bajtów jakie zajmuje macierz wejściowa możesz skorzystać z funkcji Length i SizeOf, a do skopiowania pamięci procedury Move; Przykład poniżej:

type
  TDoubleDynArray = array of Double;

var
  ddaSource, ddaDest: TDoubleDynArray;
begin
  SetLength(ddaSource, 3);
  ddaSource[0] := 3.14;
  ddaSource[1] := 2.51;
  ddaSource[2] := 4.25;

  SetLength(ddaDest, Length(ddaSource));
  Move(ddaSource[0], ddaDest[0], Length(ddaSource) * SizeOf(Double));

  WriteLn(ddaDest[0]:2:2);
  WriteLn(ddaDest[1]:2:2);
  WriteLn(ddaDest[2]:2:2);
  ReadLn;
end.

http://ideone.com/y7FqBx

To samo musisz zrobić u siebie, zastępując to sztywne przypisanie, które de facto jest błędne; Czyli w miejsce tej linijki:

TabLista^.tab := example;  // Tutaj miałaby się znajdować tablica z powyższymi danymi

wstaw te dwie poniższe:

SetLength(TabLista^.Tab, Length(Example));
Move(Example[0], TabLista^.Tab[0], Length(Example) * SizeOf(Double));

i już powinno się kompilować i działać prawidłowo, nawet jeśli macierz example będzie pusta.

0

A więc zrobiłem to tak:

 type
 TDoubleArr = array of Double;
 listaprzykladow = ^Tlistaprzykladow;
 Tlistaprzykladow = record
   Next: listaprzykladow; 
   tab: TDoubleArr;
 end;
.
.
.
public
   poczatek_list:listaprzykladow;
   nastepny:listaprzykladow;
.
.
.
procedure TForm1.ZALADUJ();
var
  TabLista:listaprzykladow;
  i:integer;
  example: TDoubleArr;
begin
  setlength(example,2);
  i:=0;
  while(i<>2) do
  begin
    Inc(i);
    poczatek_list := nil;
    nastepny := nil;
    example[0]:=i;
    example[1]:=i+1;

    New(TabLista);
    TabLista^.Next := nil;
    TabLista^.tab := example;

    if poczatek_list = nil then
    begin
       poczatek_list := TabLista;
       nastepny := poczatek_list;
    end
    else
    begin
       nastepny^.Next := TabLista;
       nastepny := TabLista;
    end;
    end;


///SPRAWDZAM ZAWARTOŚĆ LISTY


  Tablista := poczatek_list;

  while Tablista <> nil do
  begin
    for I := 0 to 1 do
    begin
      if(Tablista^.tab[i]=1) then
         showmessage('1!!! ' +floattostr(Tablista^.tab[i]))
      else
         showmessage('Różne od 1: '+floattostr(Tablista^.tab[i]))
    end;
   Tablista := Tablista^.Next;
  end;
end;

Niestety gdy chcę sprawdzić listę od początku do końca, to zawsze otrzymuję ostatnio dodaną tablicę.
Jak należałoby to zrobić?

1
setlength(example,2);
2

Czy mógłbyś zamieścić cały kod, aby można było go skompilować?

Dodatkowa tablica example jest ci tutaj nie potrzebna okazuje się, że gdybyś chciał jej jednak użyć to musisz jej elementy skopiować przy użyciu Move jak zaprezentował @furious programming zamiast zwykłego przypisania.

procedure TForm1.ZALADUJ();
var
  TabLista:listaprzykladow;
  i:integer;
begin
  i:=0;
  while(i<>2) do
  begin
    Inc(i);
    poczatek_list := nil;
    nastepny := nil;
 
    New(TabLista);
    TabLista^.Next := nil;
    SetLength(TabLista^.tab, 2)
    TabLista^.tab[0] := i;
    TabLista^.tab[1] := i+1;
0
 type
 TDoubleArr = array of Double;
 listaprzykladow = ^Tlistaprzykladow;
 Tlistaprzykladow = record
   Next: listaprzykladow;
   Dane: string;
   tab: TDoubleArr;
 end;
type
  TForm4 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
      procedure ZALADUJ();
    { Private declarations }
  public
     poczatek_list:listaprzykladow;
   nastepny:listaprzykladow;
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

procedure TForm4.Button1Click(Sender: TObject);
begin
ZALADUJ();
end;

procedure TForm4.ZALADUJ();
var
  TabLista:listaprzykladow;
  i:integer;
  example: TDoubleArr;
begin
setlength(example,2);
i:=0;
while(i<>2) do
begin
Inc(i);
poczatek_list := nil;
nastepny := nil;
example[0]:=i;
example[1]:=i+1;

New(TabLista);
TabLista^.Next := nil;
TabLista^.tab := example;


 if poczatek_list = nil then
     begin
      poczatek_list := TabLista;
      nastepny := poczatek_list;
     end
    else
     begin
    nastepny^.Next := TabLista;
      nastepny := TabLista;
     end;
end;

//Sprawdzam zawartosc listy- NIESTETY pokazuje mi dane z ostatnio dodanej tablicy
Tablista := poczatek_list;

 while Tablista <> nil do
  begin
  for I := 0 to 1 do
  begin
     if(Tablista^.tab[i]=1) then
        showmessage('1!!! ' +floattostr(Tablista^.tab[i]))
     else
        showmessage('Różna od 1: '+floattostr(Tablista^.tab[i]))
  end;
   Tablista := Tablista^.Next;
  end;

end;
end.
 

Chcę to zrobić ponieważ najpierw dodaje dane do tablicy example

 example[0]:=0;...Example[24]:=23;

Następnie chcę dodać całą tablicę do listy.
Powtarzam te kroki 9 razy.

Nie wiem jak teraz wydobyć te dane z listy, ponieważ przy sprawdzaniu pokazuje mi tylko dane z ostatnio dodanej tablicy

Proszę o pomoc

2

Nie obraź się, ale ten kod warto byłoby przepisać od początku. Przede wszystkim twoja "lista" nie działa. Doprowadź kod do stanu, w którym zamiast tej tablicy double będziesz miał tylko 1 zmienną. Jeśli to zadziała to możesz iść dalej.

Tak powinno wyglądać skopiowanie tablicy Example do TabLista^.tab:

...
    New(TabLista);
    TabLista^.Next := nil;

    SetLength(TabLista^.tab, Length(example));
    Move(example[0], TabLista^.tab[0], Length(example) * SizeOf(Double));
 
 
 if poczatek_list = nil then
...

Natomiast jak już pisałem twoja lista nie działa ma tylko 1 element.

 if poczatek_list = nil then

na początku zawsze będziesz wchodził w pierwszy blok i spoko, ale później gdy pętla wraca na początek przypisujesz mu nil - przez co jest skasowany -,- tworzysz kolejny i zostaje tylko ostatni.

Kolejna sprawa to porównywanie zmiennych zmiennoprzecinkowych http://stackoverflow.com/questions/6106119/how-to-compare-double-in-delphi

Formatowanie kodu w Delphi może nie jest to najlepszy art na ten temat, ale po polsku i pozwoli ci nieco lepiej ogarnąć kod.

2

@lukasz_p92 - może zacznij tak jak wspomniał poprzednik od implementacji gołej listy jednokierunkowej? Poza tym tworzysz aplikację okienkową, czyli de facto korzystasz z programowania obiektowego, więc opakuj sobie listę w klasę i korzystaj już wygodnie z obiektu, bez takich zabaw; Jeśli nie wiesz jak zaimplementować klasę listy, to zaglądnij do tego artykułu - http://4programmers.net/Delphi/Lista_jednokierunkowa - który opracowaliśmy z @babubabu;

Jak już zaimplementujesz sobie klasę listy, to wtedy będziesz mógł do niej wrzucać dowolne dane; Ale poprawne działanie listy jest kluczowe, więc najpierw skup się na tym zagadnieniu.

1

Nigdy nie rób kopiowania tablic przy pomocy move jest to bardzo błędogienny sposób.
Poprawne kopiowanie:

TabLista^.tab:=example;

ztym że w tym przypadku nie możesz już zmieniać tej tablicy exampleponieważ spowoduje to zmianę w TabLista^.tab.
Jeżeli chcesz dokonać "głębokiej kopii":

TabLista^.tab:=example;
SetLength(TabLista^.tab,Length(example)); // ewentualnie ... ,Length(TabLista^.tab)); 

po tym możesz zmieniać example bez żadnych następstw.

0

Dziękuję, bardzo mi pomogliście.

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