(************************************************************************)
(* Program demonstruje praci s pointery ukazujicimi na prvky statickeho *)
(* pole celych cisel.                                                   *)
(* Pohyb v poli pomoci pointeru je rychlejsi nez pomoci indexu na prvky.*)
(************************************************************************)

program pole_cisel;

uses
  crt;

const
  MAX = 20; { maximalni index pole }

var
  pole: array[1..MAX] of integer;   { pole celych cisel }
  pocet: word;                      { skutecny pocet nactenych cisel }
  prvni, posledni, p, pom: ^integer;{ pointery na dat. typ integer, budou
                                      pouzity jako ukazatele na prvky pole }

procedure Nacti;
{ nacte do pole cela cisla z klavesnice }
var
  i: word;
begin
  repeat
    write('Zadejte pocet prvku (alespon jeden, maximalne ',MAX,'): ');
    readln(pocet);
  until pocet in [1..MAX];

  prvni    := @pole[1];     { ukazatel na prvni prvek pole }
  posledni := @pole[pocet]; { ukazatel na posledni zadany prvek pole }

  clrscr;
  writeln('Zadej prvky pole - cela cisla, celkem ',pocet,':');
  for i := 1 to pocet do begin
    write(i:3, '. prvek: ');
    readln(pole[i]);
  end;
  writeln;
end;

procedure Vypis;
{ vypise zadane prvky pole }
begin
  p := prvni;               { ukazatel na prvni prvek pole, vypisujeme ... }
  writeln('Vypis pole:');   { ... od zacatku }
  repeat
    write((p^):4);          { vypiseme prvek, na ktery ukazuje pointer p }
    if p = posledni then break;{ vypsanim posledniho prvku koncime smycku }
    inc(p);                 { posun na dalsi prvek pole, v DOSu tedy o 2B }
  until false;
  writeln;
  writeln;
end;

procedure VypisZpet;
{ vypise pole pozpatku }
begin
  p := posledni;            { ukazatel na posledni prvek pole, vypisujeme }
  writeln('Vypis pole pozpatku:');                             { pozpatku }
  repeat
    write((p^):4);
    if p = prvni then break;{ smycku koncime u prvniho prvku pole }
    dec(p);                 { posun na predchozi prvek pole }
  until false;
  writeln;
  writeln;
end;

function Soucet: longint;
{ funkce vraci soucet prvku pole }
var
  s: longint;
begin
  p := prvni;
  s := 0;
  repeat
    s := s + p^;     { do prom. s pricteme hodnotu, na kterou ukazuje p }
    if p = posledni then break;
    inc(p);
  until false;
  Soucet := s;
end;

function Soucin: longint;
{ funkce vraci soucin prvku pole, ktera jsou z intervalu 1..4 }
var
  s: longint;
begin
  p := prvni;
  s := 1;
  repeat
    if p^ in [1..4] then
      s := s * p^;   { prom. s vynasobime hodnotou, na kterou ukazuje p }
    if p = posledni then break;
    inc(p);
  until false;
  Soucin := s;
end;

procedure Delitelna(cislo: integer);
{ vypise vsechna cisla, ktera jsou delitelna zadanym cislem }
begin
  p := prvni;
  writeln('Cisla delitelna cislem ',cislo, ':');
  repeat
    if (p^) mod cislo = 0 then { MOD = zbytek po celociselnem deleni }
      write((p^):4);
    if p = posledni then break;
    inc(p);
  until false;
  writeln;
  writeln;
end;

procedure KazdeDruhe;
{ vypise kazde druhe cislo, je nutne osetrit zastaveni }
begin
  if pocet > 1 then begin
    p := @pole[2];
    if odd(pocet) then pom := @pole[pocet-1] { lichy pocet prvku pole }
                  else pom := posledni;      { sudy pocet prvku pole }
    writeln('Vypis kazdeho druheho prvku:');

    repeat
      write((p^):4);
      if p = pom then break;
      inc(p,2);                              { posun o 2 prvky dale }
    until false;
    writeln;
  end;
end;


begin { hlavni program }
  clrscr;
  Nacti;

  prvni    := @pole[1];
  posledni := @pole[pocet];

  Vypis;
  VypisZpet;
  writeln('Soucet prvku pole: ',Soucet);
  writeln;
  writeln('Soucin prvku z intervalu [1..4]: ',Soucin);
  writeln;
  Delitelna(3);
  KazdeDruhe;
  readln;
end.