PROGRAMMA COMPLETO

Questo è il programma ottenuto ricombinando i vari moduli nel seguente modo: Il programma è poi stato controllato staticamente usando il compilatore del PASCAL.
program DATAB;

 const
  MAX = 100;

 type
  COMANDO = (INSERISCI, CANCELLA, CAMBIA_GRUPPO, VOTO_ORALE, VOTO_SCRITTO, 
             VOTO_PROGETTO, PASSATO, STAMPA_GRUPPI, STAMPA_MATRICOLA, 
             STAMPA_COGNOME, STAMPA_PASSATI, STATISTICHE, FINE);

  GRUPPO = 1..30;
  MATRICOLA = 100000..999999;
  VOTO = -1..33;

  PAROLA = record
    LUN: 0..30;
    CARS: array[1..30] of char;
   end;

  SCHEDA = record
    nome, cognome: PAROLA;
    gruppo: GRUPPO;
    matricola: MATRICOLA;
    orale, scritto, progetto: VOTO
   end;

  STATO = array[1..MAX] of SCHEDA;

 var
  ARCHI: STATO;
  LIBERO: integer;

  COM: COMANDO;  {MAIN}
  C: CHAR;    {MAIN}

{********************************************************************}
{                     COMANDI                                        }
{********************************************************************}

 procedure LEGGI_COMANDO (var COM: COMANDO);  {COMANDO}
  var
   N: integer;
 begin
  writeln('I comandi possibili sono:');
  writeln('1: inserisci studente');
  writeln('2: cancella studente');
  writeln('3: cambia gruppo');
  writeln('4: registra voto orale');
  writeln('5: registra voto scritto');
  writeln('6: registra voto progetto');
  writeln('7: controlla e'' passato ');
  writeln('8: stampa gruppi ');
  writeln('9: stampa matricole ');
  writeln('10: stampa nomi ');
  writeln('11: stampa passati ');
  writeln('12: statistiche ');
  writeln('13: fine ');
  readln(N);
  case N of
   1: 
    COM := INSERISCI;
   2: 
    COM := CANCELLA;
   3: 
    COM := CAMBIA_GRUPPO;
   4: 
    COM := VOTO_ORALE;
   5: 
    COM := VOTO_SCRITTO;
   6: 
    COM := VOTO_PROGETTO;
   7: 
    COM := PASSATO;
   8: 
    COM := STAMPA_GRUPPI;
   9: 
    COM := STAMPA_MATRICOLA;
   10: 
    COM := STAMPA_COGNOME;
   11: 
    COM := STAMPA_PASSATI;
   12: 
    COM := STATISTICHE;
   13: 
    COM := FINE;
  end;
 end;

 function E_FINE (COM: COMANDO): boolean;  {COMANDO}
 begin
  E_FINE := COM = FINE;
 end;

{********************************************************************}
{                      GRUPPO                                        }
{********************************************************************}

 procedure LEGGI_GRUPPO (var G: GRUPPO);
 begin
  read(G)
 end;

 procedure SCRIVI_GRUPPO (G: GRUPPO);
 begin
  write(G : 2)
 end;

{********************************************************************}
{                      MATRICOLA                                     }
{********************************************************************}

 procedure LEGGI_MAT (var M: MATRICOLA);
 begin
  read(M)
 end;

 procedure SCRIVI_MAT (M: MATRICOLA);
 begin
  write(M : 6)
 end;

{********************************************************************}
{                        VOTO                                        }
{********************************************************************}

 procedure LEGGI_VOTO (var V: VOTO);
 begin
  read(V)
 end;

 procedure SCRIVI_VOTO (V: VOTO);
 begin
  if V < 31 then
   write(V : 2)
  else
   write('30 e lode');
 end;

{********************************************************************}
{                        PAROLA                                      }
{********************************************************************}

 function UGUALE_P (P1, P2: PAROLA): boolean;
  var
   UG: boolean;
   I: integer;
 begin
  if P1.LUN <> P2.LUN then
   UGUALE_P := false
  else
  begin
   UG := true;
   I := 1;
   while UG and (I < P1.LUN) do
    if P1.CARS[I] <> P2.CARS[I] then
     UG := false
    else
     I := I + 1;
   UGUALE_P := UG;
  end;
 end;

 function MINORE_P (P1, P2: PAROLA): boolean;
  var
   FINE: boolean;
   I: integer;
 begin
  FINE := false;
  I := 1;
  while (not FINE) and (I <= P1.LUN) and (I <= P2.LUN) do
   if P1.CARS[I] = P2.CARS[I] then
    I := I + 1
   else
   begin
    MINORE_P := P1.CARS[I] < P2.CARS[I];
    FINE := true
   end;
  if not FINE then
   MINORE_P := P1.LUN < P2.LUN;
 end;

 procedure LEGGI_PAROLA (var P: PAROLA);
{legge tutti i caratteri, che costituiranno la parola, fino al primo blank}
  var
   C: char;
 begin
  P.LUN := 0;
  read(C);
  while C <> ' ' do
  begin
   P.LUN := P.LUN + 1;
   P.CARS[P.LUN] := C;
   read(C);
  end;
 end;

 procedure SCRIVI_PAROLA (P: PAROLA);
  var
   I: integer;
 begin
  for I := 1 to P.LUN do
   write(P.CARS[I]);
 end;

{********************************************************************}
{                        SCHEDA                                      }
{********************************************************************}

 function ESTRAI_GRUPPO (S: SCHEDA): GRUPPO;
 begin
  ESTRAI_GRUPPO := S.gruppo;
 end;

 procedure NOME (S: SCHEDA;
       var N: PAROLA);
 begin
  N := S.nome;
 end;

 procedure COGNOME (S: SCHEDA;
       var C: PAROLA);
 begin
  C := S.cognome;
 end;

 function MATRIC (S: SCHEDA): MATRICOLA;
 begin
  MATRIC := S.matricola;
 end;

 function VOTO_O (S: SCHEDA): VOTO;
 begin
  VOTO_O := S.orale;
 end;

 function VOTO_S (S: SCHEDA): VOTO;
 begin
  VOTO_S := S.scritto;
 end;

 function VOTO_P (S: SCHEDA): VOTO;
 begin
  VOTO_P := S.progetto;
 end;

 procedure SCHEDA_INIZIALE (N, C: PAROLA;
       MAT: MATRICOLA;
       G: GRUPPO;
       var S: SCHEDA);
 begin
  S.nome := N;
  S.cognome := C;
  S.matricola := MAT;
  S.gruppo := G;
  S.orale := -1;
  S.scritto := -1;
  S.progetto := -1;
 end;

 function VOTO_FINALE (S: SCHEDA): VOTO;
 begin
  if ((VOTO_O(S) >= 15) and ((VOTO_S(S) >= 15) and (VOTO_P(S) >= 15))) then
   VOTO_FINALE := 
      round((((VOTO_O(S) + VOTO_S(S)) / 2) * 3 / 5) + (VOTO_P(S) * 2 / 5))
  else
   VOTO_FINALE := -1
 end;

{********************************************************************}
{                             STATO                                  }
{********************************************************************}

 procedure RECUPERA_STATO;
{ recupero lo stato corrente dalla memoria di massa e lo mette in ARCHI }
{ lo stato e' conservato in un file di nome STATO_SALVATO }
  var
   F: file of SCHEDA;
 begin
  reset(F, 'STATO_SALVATO');
  LIBERO := 1;
  while (not eof(F)) do
  begin
   read(F, ARCHI[LIBERO]);
   LIBERO := LIBERO + 1;
  end;
 end;

 procedure SALVA_STATO;
{salva lo stato corrente, contenuto nella variabile ARCHI, sulla memoria di massa}
  var
   F: file of SCHEDA;
   I: integer;
 begin
  rewrite(F, 'STATO_SALVATO');
  for I := 1 to LIBERO - 1 do
   write(F, ARCHI[LIBERO]);
 end;

 procedure STATO_VUOTO;
{assegna alla variabile ARCHI l'archivio vuoto}
 begin
  LIBERO := 1;
 end;

 procedure AGGIUNGI_SCHEDA (S: SCHEDA);
{aggiunge la scheda S all'archivio contenuto nella variabile ARCHI }
 begin
  ARCHI[LIBERO] := S;
  LIBERO := LIBERO + 1;
 end;

 procedure CANCELLA_SCHEDA (M: MATRICOLA);
{cancella la scheda relativa allo studente di matricola M dall'archivio contenuto nella variabile ARCHI }
  var
   I: integer;
 begin
  I := 1;
  while I < LIBERO do
   if MATRIC(ARCHI[I]) <> M then
    I := I + 1
   else
   begin
    if I < LIBERO - 1 then
     ARCHI[I] := ARCHI[LIBERO - 1];
    LIBERO := LIBERO - 1;
    I := LIBERO;
   end;
 end;

 procedure MODIFICA_G (M: MATRICOLA;
       NUOVO_G: GRUPPO);
{ modifica il gruppo nella scheda relativa allo studente}
{ di matricola M nell'archivio contenuto nella variabile ARCHI }
  var
   I: integer;
 begin
  I := 1;
  while I < LIBERO do
   if MATRIC(ARCHI[I]) <> M then
    I := I + 1
   else
   begin
    ARCHI[I].gruppo := NUOVO_G;
    I := LIBERO;
   end;
 end;

 procedure MODIFICA_O (M: MATRICOLA;
       NUOVO_V: VOTO);
{ modifica il voto orale nella scheda relativa allo studente}
{ di matricola M nell'archivio contenuto nella variabile ARCHI }
  var
   I: integer;
 begin
  I := 1;
  while I < LIBERO do
   if MATRIC(ARCHI[I]) <> M then
    I := I + 1
   else
   begin
    ARCHI[I].orale := NUOVO_V;
    I := LIBERO;
   end;
 end;

 procedure MODIFICA_S (M: MATRICOLA;
       NUOVO_V: VOTO);
{ modifica il voto scritto nella scheda relativa allo studente}
{ di matricola M nell'archivio contenuto nella variabile ARCHI }
  var
   I: integer;
 begin
  I := 1;
  while I < LIBERO do
   if MATRIC(ARCHI[I]) <> M then
    I := I + 1
   else
   begin
    ARCHI[I].scritto := NUOVO_V;
    I := LIBERO;
   end;
 end;

 procedure MODIFICA_P (M: MATRICOLA;
       NUOVO_V: VOTO);
{ modifica il voto progetto nella scheda relativa allo studente}
{ di matricola M nell'archivio contenuto nella variabile ARCHI }
  var
   I: integer;
 begin
  I := 1;
  while I < LIBERO do
   if MATRIC(ARCHI[I]) <> M then
    I := I + 1
   else
   begin
    ARCHI[I].progetto := NUOVO_V;
    I := LIBERO;
   end;
 end;

 function E_PASSATO (M: MATRICOLA): boolean;
{ controlla se lo studente di matricola M ha passato l'esame secondo i dati }
{ presenti nell'archivio contenuto nella variabile ARCHI }
  var
   I: integer;
 begin
  I := 1;
  while I < LIBERO do
   if MATRIC(ARCHI[I]) <> M then
    I := I + 1
   else
   begin
    E_PASSATO := VOTO_FINALE(ARCHI[I]) >= 18;
    I := LIBERO;
   end;
 end;

 procedure ORDINA_ARCHIVIO (function ORD (S1, S2: SCHEDA): boolean);
{ ordina l'archivio contenuto nella variabile ARCHI secondo ORD }
  var
   C, J: integer;
   SCAMBIO: SCHEDA;
 begin
  for C := 1 to LIBERO - 1 do
  {scambio l'elemento C-esimo con il piu' piccolo degli elementi }
  { tra il C+1-esimo e l'ultimo (che sta in posto LIBERO-1) }
   for J := C + 1 to LIBERO - 1 do
    if ORD(ARCHI[J], ARCHI[C]) then
    begin
     SCAMBIO := ARCHI[C];
     ARCHI[C] := ARCHI[J];
     ARCHI[J] := SCAMBIO;
    end;
 end;

 procedure STAMPA_ARCHIVIO (procedure STAMPA_SCHEDA (S: SCHEDA));
{ stampa le schede appartenenti all'archivio contenuto nella variabile ARCHI }
{ come richiesto dalla procedura STAMPA_SCHEDA }
  var
   I: integer;
 begin
  for I := 1 to LIBERO - 1 do
   STAMPA_SCHEDA(ARCHI[I]);
 end;

 function NUM_STUD: integer;
{ ritorna il numero di schede presenti nell'archivio }
 begin
  NUM_STUD := LIBERO - 1;
 end;

 function NUM_OR: integer;
{ ritorna il numero di schede con voto orale presenti nell'archivio }
  var
   I, ORALI: integer;
 begin
  ORALI := 0;
  for I := 1 to LIBERO - 1 do
   if ARCHI[I].orale > -1 then
    ORALI := ORALI + 1;
  NUM_OR := ORALI;
 end;

 function NUM_SCR: integer;
{ ritorna il numero di schede con voto scritto presenti nell'archivio }
  var
   I, SCRITTI: integer;
 begin
  SCRITTI := 0;
  for I := 1 to LIBERO - 1 do
   if ARCHI[I].scritto > -1 then
    SCRITTI := SCRITTI + 1;
  NUM_SCR := SCRITTI;
 end;

 function NUM_PRO: integer;
{ ritorna il numero di schede con voto progetto presenti nell'archivio }
  var
   I, PROG: integer;
 begin
  PROG := 0;
  for I := 1 to LIBERO - 1 do
   if ARCHI[I].progetto > -1 then
    PROG := PROG + 1;
  NUM_PRO := PROG;
 end;

 function NUM_PAS: integer;
{ ritorna il numero di schede con esame passato presenti nell'archivio }
  var
   I, PASSATI: integer;
 begin
  PASSATI := 0;
  for I := 1 to LIBERO - 1 do
   if VOTO_FINALE(ARCHI[I]) > 17 then
    PASSATI := PASSATI + 1;
  NUM_PAS := PASSATI;
 end;

{********************************************************************}
{                     ATTIVITA'  PRINCIPALE                          }
{********************************************************************}

 procedure ESEGUI (COM: COMANDO);  {ATTIVITA' BASE}
{ Usa la variabile globale ARCHI }

  procedure INSER;
   var
    NOME, COGNOME: PAROLA;
    M: MATRICOLA;
    G: GRUPPO;
    S: SCHEDA;
  begin
   LEGGI_PAROLA(NOME);
   LEGGI_PAROLA(COGNOME);
   LEGGI_MAT(M);
   LEGGI_GRUPPO(G);
   SCHEDA_INIZIALE(NOME, COGNOME, M, G, S);
   AGGIUNGI_SCHEDA(S);
  end; {INSER}

  procedure CANC;
   var
    M: MATRICOLA;
  begin
   LEGGI_MAT(M);
   CANCELLA_SCHEDA(M);
  end; {CANC}

  procedure CAMBIA_G;
   var
    M: MATRICOLA;
    G: GRUPPO;
  begin
   LEGGI_MAT(M);
   LEGGI_GRUPPO(G);
   MODIFICA_G(M, G);
  end; {CAMBIA_G}

  procedure VOTO_O;
   var
    M: MATRICOLA;
    V: VOTO;
  begin
   LEGGI_MAT(M);
   LEGGI_VOTO(V);
   MODIFICA_O(M, V);
  end; {CAMBIA_O}

  procedure VOTO_S;
   var
    M: MATRICOLA;
    V: VOTO;
  begin
   LEGGI_MAT(M);
   LEGGI_VOTO(V);
   MODIFICA_S(M, V);
  end; {CAMBIA_S}

  procedure VOTO_P;
   var
    M: MATRICOLA;
    V: VOTO;
  begin
   LEGGI_MAT(M);
   LEGGI_VOTO(V);
   MODIFICA_P(M, V);
  end; {CAMBIA_P}

  procedure PASS;
   var
    M: MATRICOLA;
  begin
   LEGGI_MAT(M);
   write('Lo studente di matricola ');
   SCRIVI_MAT(M);
   write(' ');
   if E_PASSATO(M) then
    writeln(' e'' passato.')
   else
    writeln(' non e'' passato.')
  end; {PASS}

  procedure STAMPA_G;

   function ORDINE_G (S1, S2: SCHEDA): boolean;
    var
     N1, C1, N2, C2: PAROLA;
     G1, G2: GRUPPO;
   begin
    NOME(S1, N1);
    COGNOME(S1, C1);
    NOME(S2, N2);
    COGNOME(S2, C2);
    G1 := ESTRAI_GRUPPO(S1);
    G2 := ESTRAI_GRUPPO(S2);
    if G1 = G2 then
     if UGUALE_P(C1, C2) then
      ORDINE_G := MINORE_P(N1, N2)
     else
      ORDINE_G := MINORE_P(C1, C2)
    else
     ORDINE_G := G1 < G2;
   end;

   procedure VISTA_G (S: SCHEDA);
    var
     N, C: PAROLA;
   begin
    SCRIVI_GRUPPO(ESTRAI_GRUPPO(S));
    write(' ');
    COGNOME(S, C);
    SCRIVI_PAROLA(C);
    write(' ');
    NOME(S, N);
    SCRIVI_PAROLA(N);
    writeln;
   end;

  begin
   ORDINA_ARCHIVIO(ORDINE_G);
   STAMPA_ARCHIVIO(VISTA_G);
  end; {STAMPA_G}

  procedure STAMPA_M;

   function ORDINE_M (S1, S2: SCHEDA): boolean;
   begin
    ORDINE_M := MATRIC(S1) < MATRIC(S2);
   end;

   procedure VISTA_M (S: SCHEDA);
    var
     N, C: PAROLA;
   begin
    SCRIVI_MAT(MATRIC(S));
    write(' ');
    COGNOME(S, C);
    SCRIVI_PAROLA(C);
    write(' ');
    NOME(S, N);
    SCRIVI_PAROLA(N);
    writeln;
   end;

  begin
   ORDINA_ARCHIVIO(ORDINE_M);
   STAMPA_ARCHIVIO(VISTA_M);
  end; {STAMPA_M}

  procedure STAMPA_C;

   function ORDINE_C (S1, S2: SCHEDA): boolean;
    var
     N1, C1, N2, C2: PAROLA;
   begin
    NOME(S1, N1);
    COGNOME(S1, C1);
    NOME(S2, N2);
    COGNOME(S2, C2);
    if UGUALE_P(C1, C2) then
     ORDINE_C := MINORE_P(N1, N2)
    else
     ORDINE_C := MINORE_P(C1, C2)
   end;

   procedure VISTA_C (S: SCHEDA);
    var
     N, C: PAROLA;
   begin
    COGNOME(S, C);
    SCRIVI_PAROLA(C);
    write(' ');
    NOME(S, N);
    SCRIVI_PAROLA(N);
    writeln;
   end;

  begin
   ORDINA_ARCHIVIO(ORDINE_C);
   STAMPA_ARCHIVIO(VISTA_C);
  end; {STAMPA_C}

  procedure STAMPA_PAS;

   function ORDINE_PAS (S1, S2: SCHEDA): boolean;
    var
     N1, C1, N2, C2: PAROLA;
     V1, V2: VOTO;
   begin
    NOME(S1, N1);
    COGNOME(S1, C1);
    NOME(S2, N2);
    COGNOME(S2, C2);
    V1 := VOTO_FINALE(S1);
    V2 := VOTO_FINALE(S2);
    if V1 = V2 then
     if UGUALE_P(C1, C2) then
      ORDINE_PAS := MINORE_P(N1, N2)
     else
      ORDINE_PAS := MINORE_P(C1, C2)
    else
     ORDINE_PAS := V1 < V2;
   end;

   procedure VISTA_PAS (S: SCHEDA);
    var
     N, C: PAROLA;
     V: VOTO;
   begin
    V := VOTO_FINALE(S);
    if V >= 18 then
    begin
     COGNOME(S, C);
     SCRIVI_PAROLA(C);
     write(' ');
     NOME(S, N);
     SCRIVI_PAROLA(N);
     write(' voto finale = ');
     SCRIVI_VOTO(V);
     writeln;
    end
   end;

  begin
   ORDINA_ARCHIVIO(ORDINE_PAS);
   STAMPA_ARCHIVIO(VISTA_PAS);
  end; {STAMPA_PAS}

  procedure STA;
   var
    NS: integer;
  begin
   NS := NUM_STUD;
   Writeln('Totale studenti = ', NS);
   Writeln('Percentuale superato esame = ', ((NUM_PAS * 100) / NS) : 2);
   Writeln('Percentuale superato scritto = ', ((NUM_SCR * 100) / NS) : 2);
   Writeln('Percentuale superato orale = ', ((NUM_OR * 100) / NS) : 2);
   Writeln('Percentuale superato progetto = ', ((NUM_PRO * 100) / NS) : 2);
  end; {STA}

 begin {ESEGUI}
  case COM of
   INSERISCI: 
    INSER;
   CANCELLA: 
    CANC;
   CAMBIA_GRUPPO: 
    CAMBIA_G;
   VOTO_ORALE: 
    VOTO_O;
   VOTO_SCRITTO: 
    VOTO_S;
   VOTO_PROGETTO: 
    VOTO_P;
   PASSATO: 
    PASS;
   STAMPA_GRUPPI: 
    STAMPA_G;
   STAMPA_MATRICOLA: 
    STAMPA_M;
   STAMPA_COGNOME: 
    STAMPA_C;
   STAMPA_PASSATI: 
    STAMPA_PAS;
   STATISTICHE: 
    STA;
   FINE: 
  end;
 end; {ESEGUI}


begin   {MAIN}
 writeln('Vuoi recuperare lo stato iniziale ? (S/N)?');
 readln(C);
 if C = 'S' then
  RECUPERA_STATO
 else
  STATO_VUOTO;

 repeat
  LEGGI_COMANDO(COM);
  ESEGUI(COM);
 until E_FINE(COM);

 SALVA_STATO;
end.    {MAIN}