{ File: palin4.pas }

{ Scopo: record e file di testo }

program StringheDaFilePalindrome;
{ Legge una sequenza di caratteri da file e determina se e` palindroma.
  - la lunghezza MASSIMA della sequenza e` fissata

  In questa versione
  - vengono ignorati tutti i caratteri diversi da lettere alfabetiche e cifre
  - viene ignorata la differenza tra lettere minuscole e maiuscole
}

const
  LunghezzaMax = 500;

type
  TipoIndice       = 1..LunghezzaMax;
  TipoArrayStringa = packed array [TipoIndice] of char;
  TipoStringa      = record
                       caratteri : TipoArrayStringa;
                       lunghezza : 0..LunghezzaMax
                     end;        


  procedure LeggiStringa (var stringa: TipoStringa);
  { Legge un file e restituisce in stringa la sequenza di caratteri
    alfanumerici contenuti nel file.  Converte le lettere in maiuscole.
  }

  var
    ch       : char;      { carattere corrente }
    continua : boolean;   { indica se continuare la lettura o terminare perche`
                            si e` superata la dimensione del vettore di
                            caratteri }
    nome     : string;    { nome fisico }
    f        : text;      { nome logico }

    function Maiuscola (c: char): char;
    begin { Maiuscola }
      if ('a' <= c) and (c <= 'z') then
        Maiuscola := chr(ord(c) - ord('a') + ord('A'))
      else
        Maiuscola := c
    end; { Maiuscola }

    function AlfaNumerico (c: char): boolean;
    begin { AlfaNumerico }
      AlfaNumerico := (('A' <= c) and (c <= 'Z')) or
                      (('a' <= c) and (c <= 'z')) or
                      (('0' <= c) and (c <= '9'))
    end; { AlfaNumerico }
  
  begin { LeggiStringa }
    writeln('Nome del file contenente la stringa? ');
    readln(nome);

    Assign(f, nome);
    Reset(f);

    continua := TRUE;
    with stringa do
    begin
      lunghezza := 0;
      while (not eof(f)) and continua do
      begin
        read(f, ch);
        if AlfaNumerico(ch) then
          if lunghezza < LunghezzaMax then
          begin
            lunghezza := lunghezza + 1;
            caratteri[lunghezza] := Maiuscola(ch);
          end
          else
          begin
            continua := FALSE;
            writeln ('File troppo lungo!')
          end
      end
    end;
    Close(f)
  end; { LeggiStringa }


  function Palindroma (stringa: TipoStringa): boolean;
  { Verifica se una stringa e` palindroma. }
  var
    i : TipoIndice;

  begin { Palindroma}
    Palindroma := TRUE;                      { assumiamo che sia palindroma }
    for i := 1 to trunc(stringa.lunghezza/2) do
      if stringa.caratteri[i] <> stringa.caratteri[stringa.lunghezza-i+1] then
        { appena viene trovato una coppia di elementi che NON soddisfa la
          condizione sappiamo che la stringa NON e` palindroma }
        Palindroma := FALSE
      { N.B. NON c'e' il ramo else }
  end; { Palindroma }


{ N.B. Nel PASCAL standard le dichiarazioni di variabili devono precedere le
       dichiarazioni di procedure e funzioni. }

var
  s  : TipoStringa;

begin { StringheDaFilePalindrome }
  LeggiStringa(s);
  write('La stringa letta contiene ', s.lunghezza,
        ' caratteri alfanumerici ');
  if Palindroma(s) then
    writeln('ed e'' palindroma')
  else
    writeln('e non e'' palindroma');
end. { StringheDaFilePalindrome }