Pascal zmienne dynamiczne

0

Witam jestem tu nowy... Programowanie mam niby już od roku ale ten nasz nauczyciel... Dobra przejdę do sedna sprawy na zajęciach z programowania dostaliśmy do zrobienia programik, który ma utworzyć listę zmiennych a potem ją wyświetlić... W szkole nam nie wychodziło to dostaliśmy do domu... Coś tam z kumplem naskrobałem ale wypisuje nam tylko pierwszą zmienną którą podamy a reszty nie ma... Prosiłbym o małą pomoc z tym

program ZmienneDynamiczne;
uses crt;
type
 w=^element;
 element=record
 wart:integer;
 nast:w;

end;


 var nowy, lista:^element;
 procedure TworzEListy(poprz:element;wart:integer);


 begin
  new(nowy);
  nowy^.wart:=wart;
  poprz.nast:=nowy;

 end;

 procedure tliste();
 var w:integer;
 begin
    new(lista);
  readln(w);
  lista^.wart:=w;
  nowy:=lista;
  readln(w);
 while w<>0 do

 begin
   TworzEListy(nowy^,w);
   readln(w);
 end;
end;

 procedure WListe;
 begin
  writeln('wypisanie listy');
  writeln(lista^.wart);
  nowy:=lista^.nast;
  while nowy <> nil do
   begin
   writeln(nowy^.wart);
   nowy:=nowy^.nast;
   end;
 end;


begin
 tliste;
 writeln('utworzono liste');
 Wliste;
 readln;
 clrscr;

end. 
0

A nie lepiej zrobić tablicę?

0

Tablice już mieliśmy na lekcjach. Byłoby łatwiej ale Prof kazał zrobić tym a nie innym sposobem....

0

Tablice są wolniejsze w odczycie/zapisu od list.

Na jakiej podstawie tak uważasz?
Tablica to miejsce w pamięci gdzie kompilator sobie wylicza miejsce (pozycja+indeks*rozmiar_indeksu) a w liscie zeby odczytac ostatni element 100000 elementowej listy, musisz przejsc przez wszystkie inne (czytaj, wybierz nast, czytaj wybierz nast, czytaj [..]). Więc jak dla mnie to tablice są zdecydowanie szybsze... Już nie mówiąc o tym że łatwiejsze w użyciu.

0

Wyniki mówią same za siebie:

{$APPTYPE CONSOLE}
Program Test;
Uses Windows, SysUtils, Classes;
Const Iter = 10000;
Var Time, Time1, Time2: Cardinal;
    I                 : Integer;
    Arr               : Array of String;
    SL                : TStringList;
    Tmp               : String;
Begin
 Time := GetTickCount;
 SL   := TStringList.Create;
 For I := 0 To Iter Do
  SL.Add('Hello');
 For I := 0 To Iter Do
  Tmp := SL[I];
 Time  := GetTickCount-Time;
 Time1 := Time;
 WriteLn('TStringList    : ', Time1, 'ms');
 Time  := GetTickCount;
 SetLength(Arr, 0); (* Przypuszczamy, że nie wiemy, ile ma być elementów *)
 For I := 0 To Iter Do
 Begin
  SetLength(Arr, High(Arr)+2);
  Arr[I] := 'Hello';
 End;
 For I := 0 To Iter Do
  Tmp := Arr[I];
 Time  := GetTickCount-Time;
 Time2 := Time;
 WriteLn('Array of String: ', Time2, 'ms');
 ReadLn;
End.

U mnie:

TStringList    : 0ms
Array of String: 1809ms

Dla 100000 iteracji:

TStringList    : 87ms
Array of String: (po dwóch minutach wywaliło "Out of memory")
0
For I := 0 To Iter Do
   SetLength(Arr, High(Arr)+2);

I ty się dziwisz, że to jest wolne?

0

Jeżeli z góry znamy ilość elementów, bądź nie będziemy ich często zwiększać, to tablica jest lepsza.

Domyślna implementacja tablicy dynamicznej zwiększa jej rozmiar fizyczny *2 gdy brakuje miejsca, zaimplementuj tak samo, będzie dużo szybciej.

0
Patryk27 napisał(a)

Wyniki mówią same za siebie:

{$APPTYPE CONSOLE}
Program Test;
Uses Windows, SysUtils, Classes;
Const Iter = 10000;
Var Time, Time1, Time2: Cardinal;
    I                 : Integer;
    Arr               : Array of String;
    SL                : TStringList;
    Tmp               : String;
Begin
 Time := GetTickCount;
 SL   := TStringList.Create;
 For I := 0 To Iter Do
  SL.Add('Hello');
 For I := 0 To Iter Do
  Tmp := SL[I];
 Time  := GetTickCount-Time;
 Time1 := Time;
 WriteLn('TStringList    : ', Time1, 'ms');
 Time  := GetTickCount;
 SetLength(Arr, 0); (* Przypuszczamy, że nie wiemy, ile ma być elementów *)
 For I := 0 To Iter Do
 Begin
  SetLength(Arr, High(Arr)+2);
  Arr[I] := 'Hello';
 End;
 For I := 0 To Iter Do
  Tmp := Arr[I];
 Time  := GetTickCount-Time;
 Time2 := Time;
 WriteLn('Array of String: ', Time2, 'ms');
 ReadLn;
End.

U mnie:

TStringList    : 0ms
Array of String: 1809ms

Dla 100000 iteracji:

TStringList    : 87ms
Array of String: (po dwóch minutach wywaliło "Out of memory")

Ten test jest do d..y. Poczytaj o TStringList.Capacity.

0

Przecież napisałem, że z założenia nie mamy znać ilości elementów, więc jak chcesz tego użyć?

Wydaje mi się, że chodziło mu o to że TStringList używa właśnie zoptymalizowanego arraya...
Nie wiem czemu zakładasz że TStringList używa listy albo czegoś innego.

0

Czy ktoś pomoże mi z tym? Może jest jakiś błąd?

0

@Patryk27
Czytałeś to?

Adding new strings will cause the Capacity property to increase if necessary

Aby dać szansę wykazania się tablicy dynamicznej trzeba zwiększać jej długość nie za każdym razem gdy dodajesz element.
Mniej więcej tak:

const delta=1000;// dobrać doświadczanie?
//...
 SetLength(Arr,delta);//wartość początkowa
 For I := 0 To Iter Do
 Begin
  if i>High(arr) then SetLength(Arr,Length(arr)+delta);
  Arr[I] := 'Hello';
 End;
 //i ew. wyrównać długość tablicy
 SetLength(Arr,Iter+1);

0
program listmake;

uses
  crt;

type
  pelement = ^element;

  element = record
    wart: integer;
    nast: pelement;

  end;


var
  lista,ost: pelement;

  function TworzEListy(poprz:pelement; wart: integer):pelement;
  var nowy:pelement;
  begin
    new(nowy);
    nowy^.wart := wart;
    poprz^.nast := nowy;
    result:=nowy;
  end;

  procedure tliste();
  var
    w: integer;
    ost,nast:pelement;
  begin
    new(lista);
    readln(w);
    lista^.wart := w;
    ost:=lista;
    readln(w);
    while w <> 0 do

    begin
      nast:=TworzEListy(ost, w);
      ost^.nast:=nast;
      ost:=nast;
      readln(w);
    end;
    ost^.nast:=nil;
  end;

  procedure WListe;
  var
    nowy:Pelement;
  begin
    writeln('wypisanie listy');
    writeln(lista^.wart);
    nowy := lista^.nast;
    while nowy <> nil do
    begin
      writeln(nowy^.wart);
      nowy := nowy^.nast;
    end;
  end;


begin
  tliste;
  writeln('utworzono liste');
  Wliste;
  readln;
  clrscr;

end.

Tyle błędów że szkoda wymieniać. Teraz powinno działać.

0

Wywala mi błąd przy result (identifier not found).

0

Nie wiem w czym to kompilujesz ale jak w TP to trzeba wynik funkcji zwracać w ten sposób:

TworzEListy:=nowy;
0

Wywala mi błąd przy result (identifier not found).

No dzięki że podziękowałeś za zainteresowanie i poświęcenie czasu!

Kompilowane pod Lazarusem 0.9.30.2 RC1, działało bez zarzutu. Chyba masz aż tyle oleju w głowie żeby poprawić jeden mały błąd? Jeśli nie to powiem: jeśli twój kompilator nie wspiera result, to powinieneś zmienić kompilator. Ale jeżeli nie możesz, to result wystarczy zmienić na nazwę funkcji (tak jak już inni wspomnieli).

Tak swoją drogą, ciekawe czy napisałeś to samemu, skoro nie możesz poprawić takiego błędu. No, ale po ilości błędów logicznych widać że jak nie działało to wywalałeś linię (sic). eh...

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