unit uloziste;
{Definujeme-li tridu v unite, metody definujeme az v sekci implementation.}

{-----------------TVypsatelny------------------}
{Tento objekt nebudeme ve skutecnosti nikdy pouzivat,
slouzi pouze jako abstraktni predek pro vsechny mozne
vypsatelne tridy. Takovymto tridam se rika abstraktni.}
interface
type    PVypsatelny=^TVypsatelny;
        TVypsatelny=object
                       constructor Init;
                       destructor Done;virtual;      {Destruktor je virtualni vzdy}
                       function Vypis:string;virtual;
                 end;


implementation

{--------------------------TVypsatelny------------------------}
constructor TVypsatelny.Init;
begin
end;

destructor TVypsatelny.Done;
begin
end;

function TVypsatelny.Vypis;
begin
 Vypis:='';
end;
{---------------------end of TVypsatelny----------------------}


begin
end.


***************************************************************************************************************
***************************************************************************************************************

unit uloziste;
interface
type    PVypsatelny=^TVypsatelny;
        TVypsatelny=object
                       constructor Init;
                       destructor Done;virtual;
                       function Vypis:string;virtual;
                 end;


implementation

{--------------------------TVypsatelny------------------------}
constructor TVypsatelny.Init;
begin
end;

destructor TVypsatelny.Done;
begin
end;

function TVypsatelny.Vypis;
begin
 Vypis:='';
end;
{---------------------end of TVypsatelny----------------------}


begin
end.
{=================================KONEC UNITY=================================}

program test;
uses uloziste;
{--------------------TKomplexniCisla--------------------------}
type PKomplexniCisla=^TKomplexniCisla;
     TKomplexniCisla=
     object(TVypsatelny)
           Re:Integer; {Komplexnim cislu s celociselnou realnou
                       i imaginarni casti se rika Gaussova,
                       budu radeji vypisovat je, jelikoz
                       vypis realnych cisel se mi libi mene.}
           Im:Integer;
           function vypis:string;virtual; {Tridu TVypsatelny s virutalni
                                          metodou Vypis mame proto, abychom
                                          mohli Vypis predefinovat,
                                          a aby pokazde delala to co chceme.}
     end;

function TKomplexniCisla.vypis;
var s1,s2:string;
begin
 s1:='';
 s2:='';
 Str(Re,s1);
 if Im<0 then
    begin
         Str(-Im,s2);
         vypis:=s1+' - '+s2+'i';
    end
  else
    begin
         Str(Im,s2);
         vypis:=s1+' + '+s2+'i';
    end;
end;
{--------------------end of TKomplexniCisla----------------------}

{-------------------------TString---------------------------}
type
    PString=^TString;
    TString=
            object(TVypsatelny)
                  s:string;
                  function vypis:string;virtual;
            end;
function TString.vypis;
begin
     vypis:=s;
end;
{----------------------end of TString----------------------}


var cislo:PKomplexniCisla;
    s:PString;
    v:PVypsatelny;
begin
 {Test - komplexni cisla}
 cislo:=New(PKomplexniCisla,Init);
 cislo^.Re:=0;
 cislo^.Im:=-1;

 v:=cislo;
 writeln(v^.vypis);
 dispose(v,done);

 {Test - retezce}
 s:=New(PString,Init);
 s^.s:='Ahoj Karle';

 v:=s;
 writeln(v^.vypis);
 dispose(v,done);

 readln;
end.
{=====================================KONEC PROGRAMU=========================}

**********************************************************************************************************
**********************************************************************************************************

unit uloziste;
interface
const maxrozsah=100;
type    PVypsatelny=^TVypsatelny;
        TVypsatelny=object
                       constructor Init;
                       destructor Done;virtual;
                       function Vypis:string;virtual;
                 end;

        PUloziste=^TUloziste;
        TUloziste=
                  object(TVypsatelny)
                        data:array[1..maxrozsah] of PVypsatelny;
                        obsazeno:integer;
                        constructor Init;
                        destructor Done;virtual;
                        function vypis:string;virtual;
                        function put(pdata:PVypsatelny):integer;
                        {Vraci 0 v pripade uspechu, -1 v pripade neuspechu (doslo-li misto).}
                  end;


implementation

{--------------------------TVypsatelny------------------------}
constructor TVypsatelny.Init;
begin
end;

destructor TVypsatelny.Done;
begin
end;

function TVypsatelny.Vypis;
begin
 Vypis:='';
end;
{---------------------end of TVypsatelny----------------------}

{-------------------------TUloziste---------------------------}
constructor TUloziste.Init;
var i:integer;
begin
 obsazeno:=0;
 for i:=1 to maxrozsah do
  data[i]:=nil;  {Ukazatele musime inicializovat vzdy; jinak hrozi katastrofa}
end;

destructor TUloziste.Done;
var i:integer;
begin
 for i:=1 to obsazeno do
  Dispose(data[i],done); {Musime zrusit vsechny prvky, ktere jsme sem
                         ulozili. (Druha moznost je nechat to na uzivateli,
                         zalezi na tom, k cemu ma uloziste slouzit.)
                         My ho budeme pouzivat tak, ze do nej umistime
                         prvek, ktery od nas bude od te chvile existovat
                         jenom v danem ulozisti.
                         Tady jiz zacina byt patrne, proc je volani
                         destruktoru dulezite.}
end;

function TUloziste.vypis:string;
var s:string;
    i:integer;
begin
 s:='';
 for i:=1 to obsazeno do
  s:=s+data[i]^.vypis+'; ';
 vypis:=s;
end;

function TUloziste.put(pdata:PVypsatelny):integer;
begin
 if obsazeno<maxrozsah then
    begin
         obsazeno:=obsazeno+1;
         data[obsazeno]:=pdata;
         put:=0; {Nedoslo k chybe}
    end
    else
    put:=-1; {Malo mista}
end;
{-------------------------end of TUloziste---------------------------}

begin
end.
{===============================END OF UNIT======================================}

program test;
uses uloziste;
{--------------------TKomplexniCisla--------------------------}
type PKomplexniCisla=^TKomplexniCisla;
     TKomplexniCisla=
     object(TVypsatelny)
           Re:Integer; {Komplexnim cislu s celociselnou realnou
                       i imaginarni casti se rika Gaussova,
                       budu radeji vypisovat je, jelikoz
                       vypis realnych cisel se mi libi mene.}
           Im:Integer;
           function vypis:string;virtual; {Tridu TVypsatelny s virutalni
                                          metodou Vypis mame proto, abychom
                                          mohli Vypis predefinovat,
                                          a aby pokazde delala to co chceme.}
     end;

function TKomplexniCisla.vypis;
var s1,s2:string;
begin
 s1:='';
 s2:='';
 Str(Re,s1);
 if Im<0 then
    begin
         Str(-Im,s2);
         vypis:=s1+' - '+s2+'i';
    end
  else
    begin
         Str(Im,s2);
         vypis:=s1+' + '+s2+'i';
    end;
end;
{--------------------end of TKomplexniCisla----------------------}

{-------------------------TString---------------------------}
type
    PString=^TString;
    TString=
            object(TVypsatelny)
                  s:string;
                  function vypis:string;virtual;
            end;
function TString.vypis;
begin
     vypis:=s;
end;
{----------------------end of TString----------------------}


var cislo:PKomplexniCisla;
    s:PString;
    sklad:PUloziste;
    v:PVypsatelny;
begin
 sklad:=new(PUloziste,Init);
 {Test - jdou do uloziste ukladat komplexni cisla?}
 cislo:=New(PKomplexniCisla,Init);
 cislo^.Re:=0;
 cislo^.Im:=-1;

 if sklad^.put(cislo)<0 then writeln('Malo mista na ulozeni promenne');
 cislo:=nil;


 {Test retezcu}
 s:=New(PString,Init);
 s^.s:='Ahoj Karle';

 if sklad^.put(s)<0 then writeln('Malo mista na ulozeni promenne');
 s:=nil;

 writeln(sklad^.vypis);
 writeln(sklad^.getfirst^.vypis);
 dispose(sklad,done);
 readln;
end.
{==´===============================END OF PROGRAM========================================}
{POZNAMKA: Od ted budeme vyuzivat stale stejny testovaci program, menit budeme pouze unitu.
Takze program test.pas nebudu kopirovat stale znova}
*********************************************************************************************
*********************************************************************************************

unit uloziste;
interface
const maxrozsah=100;
type    PVypsatelny=^TVypsatelny;
        TVypsatelny=object
                       constructor Init;
                       destructor Done;virtual;
                       function Vypis:string;virtual;
                 end;

        PUloziste=^TUloziste;
        TUloziste=
                  object(TVypsatelny)
                        data:array[1..maxrozsah] of PVypsatelny;
                        obsazeno:integer;
                        aktualni:integer;
                        constructor Init;
                        destructor Done;virtual;
                        function vypis:string;virtual;
                        function put(pdata:PVypsatelny):integer;
                        function getfirst:PVypsatelny; {v pripade chyby vrati nil}
                        function getnext:PVypsatelny; {v pripade chyby vrati nil}
                        {Vraci 0 v pripade uspechu, -1 v pripade neuspechu (doslo-li misto).}
                  end;


implementation

{--------------------------TVypsatelny------------------------}
constructor TVypsatelny.Init;
begin
end;

destructor TVypsatelny.Done;
begin
end;

function TVypsatelny.Vypis;
begin
 Vypis:='';
end;
{---------------------end of TVypsatelny----------------------}

{-------------------------TUloziste---------------------------}
constructor TUloziste.Init;
var i:integer;
begin
 obsazeno:=0;
 aktualni:=-1;
 for i:=1 to maxrozsah do
  data[i]:=nil;  {Ukazatele musime inicializovat vzdy; jinak hrozi katastrofa}
end;

destructor TUloziste.Done;
var i:integer;
begin
 for i:=1 to obsazeno do
  Dispose(data[i],done); {Musime zrusit vsechny prvky, ktere jsme sem
                         ulozili. (Druha moznost je nechat to na uzivateli,
                         zalezi na tom, k cemu ma uloziste slouzit.)
                         My ho budeme pouzivat tak, ze do nej umistime
                         prvek, ktery od nas bude od te chvile existovat
                         jenom v danem ulozisti.
                         Tady jiz zacina byt patrne, proc je volani
                         destruktoru dulezite.}
end;

function TUloziste.vypis:string;
var s:string;
    i:integer;
begin
 s:='';
 for i:=1 to obsazeno do
  s:=s+data[i]^.vypis+'; ';
 vypis:=s;
end;

function TUloziste.put(pdata:PVypsatelny):integer;
begin
 if obsazeno<maxrozsah then
    begin
         obsazeno:=obsazeno+1;
         data[obsazeno]:=pdata;
         put:=0; {Nedoslo k chybe}
    end
    else
    put:=-1; {Malo mista}
end;

function TUloziste.getfirst:PVypsatelny;
begin
 if obsazeno>0 then
    begin
         aktualni:=1;
         getfirst:=data[1];
    end
 else
     getfirst:=nil;
end;


function TUloziste.getnext:PVypsatelny;
begin
 if (aktualni>0) and (aktualni<=obsazeno)then
    begin
         aktualni:=aktualni+1;
         getnext:=data[aktualni];
    end
 else
     begin
          getnext:=nil;
          aktualni:=-1;
     end;
end;

{-------------------------end of TUloziste---------------------------}

begin
end.

************************************************************************************************
************************************************************************************************
unit uloziste;
interface
const maxrozsah=100;
type    PVypsatelny=^TVypsatelny;
        TVypsatelny=object
                       constructor Init;
                       destructor Done;virtual;
                       function Vypis:string;virtual;
                 end;

        pitem    =^item;
        item     =
                 record
                        next:pitem;
                        data:pvypsatelny;
                 end;

        PUloziste=^TUloziste;
        TUloziste=
                  object(TVypsatelny)
                        first:pitem;
                        now:pitem;
                        last:pitem;
                        constructor Init;
                        destructor Done;virtual;
                        function vypis:string;virtual;
                        function put(pdata:PVypsatelny):integer;
                        function getfirst:PVypsatelny; {v pripade chyby vrati nil}
                        function getnext:PVypsatelny; {v pripade chyby vrati nil}
                        {Vraci 0 v pripade uspechu, -1 v pripade neuspechu (doslo-li misto).}
                  end;


implementation

{--------------------------TVypsatelny------------------------}
constructor TVypsatelny.Init;
begin
end;

destructor TVypsatelny.Done;
begin
end;

function TVypsatelny.Vypis;
begin
 Vypis:='';
end;
{---------------------end of TVypsatelny----------------------}

{-------------------------TUloziste---------------------------}
constructor TUloziste.Init;
var i:integer;
begin
 first:=new(pitem); {pozor, tohle neni objekt!}
 first^.next:=first;
 first^.data:=nil;
 now:=first;
 last:=first;
end;

destructor TUloziste.Done;
begin
 last:=first^.next;
 while last<>first do
       begin
            now:=last^.next;
            dispose(last^.data,done);  {Zrusime data}
            dispose(last);             {A polozku na ne ukazujici}
            last:=now;
       end;
 dispose(first); {Zrusime hlavicku}
 first:=nil; {Je zbytecne ukazatele nulovat, ale pro pripad,
             ze by nekdo chtel pouzit zrusenou dynamickou promennou,
             se to vyplati.}
 now:=nil;
 last:=nil;
end;

function TUloziste.vypis:string;
var s:string;
    p:pitem;
begin
 p:=first^.next;
 s:='';
 while p<>first do
       begin
            s:=s+p^.data^.vypis+'; ';
            p:=p^.next;
       end;
 vypis:=s;
end;

function TUloziste.put(pdata:PVypsatelny):integer;
begin
 now:=last;
 last:=new(pitem);
 now^.next:=last;
 last^.data:=pdata;
 last^.next:=first;
 now:=first;

 put:=0; {K chybe dojde az pri opravdu velkem objemu dat,
         takze ted nema smysl to kontrolovat}
end;

function TUloziste.getfirst:PVypsatelny;
begin
 getfirst:=first^.next^.data;
end;


function TUloziste.getnext:PVypsatelny;
begin
 getnext:=now^.next^.data;
end;

{-------------------------end of TUloziste---------------------------}

begin
end.