Pascal - Tutto per la gloria di Dio

Programmazione
Tutto per la gloria di Dio.
1
Introduzione
Un programma `e un piano di azione che deve essere eseguito da un
esecutore, di solito uno strumento automatico, la maggior parte delle volte
un computer.
Un programma consiste in un insieme finito di comandi, o istruzioni, ognuno dei quali f`a eseguire all’esecutore una particolare operazione elementare
sui dati, che sono memorizzati nella memoria dell’esecutore e i cui nomi sono
i parametri dei comandi.
Si ottiene l’automatismo dell’esecutore dal fatto che ogni comando corrente, eccetto il comando stop, punta unicamente ad un comando del programma che deve essere eseguito dopo quello corrente.
Una caratteristica particolare dell’esecutore `e la presenza di comandi ramificati (transizioni condizionali) nei quali la scelta di una tra pi`
u azioni indicate viene fatta sulla base di propriet`a da verificare dei dati menzionati nel
comando.
Da ci`o ne consegue che quando si usa un programma, la successione dei
comandi pu`o variare, dopo aver definito in maniera unica i dati. Perci`o un
programma, sebbene sia un oggetto finito, permette all’utente di lavorare su
una variet`a di dati potenzialmente infinita.
I programmi sono importanti non solo come prescrizioni per computers,
ma anche come sorgenti di conoscenza operazionale degli uomini.
1
2
2
Uno sguardo all’interno
Abbiamo detto che un programma `e una successione finita di istruzioni
che agiscono su dati in memoria.
Per arginare la complessit`a di un programma, `e utile isolare sottosuccessioni di istruzioni, dette procedure, che si ripetono e che eseguono specifiche
azioni, e raggruppare tali procedure in differenti moduli, detti unit`
a.
Il tutto in un’ottica di dividere sistematicamente il problema in parti
strutturate, per agevolarne la comprensione, la produzione, la gestione, la
costante rielaborazione, il riutilizzo, la semplificazione, la lettura.
Per una buona gestione della memorizzazione e dell’elaborazione dei dati,
questi ultimi vengono divisi in tipi. Elementi di uno stesso tipo occupano
indicativamente identici spazi di memoria, e su di essi agiscono identiche
operazioni.
Tra i vari tipi di dati, si possono riconoscere, oltre a quelli semplici (numeri
interi, numeri reali, caratteri, stringhe di testo, vero o falso, ecc.), gli array,
ovvero tipi composti da un numero fissato di dati semplici di uno stesso tipo
(coppie di numeri reali, matrici 3x3 di numeri interi, ecc.) e i record, cio`e
tipi strutturati mediante un numero fissato di dati di vario tipo (una coppia
di un numero intero e una stringa).
All’interno di uno stesso tipo possiamo isolare quei dati che rimangono
invariati, le costanti, e quei dati che possono cambiare, le variabili.
3
3
Linguaggi di programmazione
Lo scopo di base di un linguaggio di programmazione `e quello di
programmare, cio`e formulare programmi che possono essere eseguiti su un
computer.
Come nei linguaggi naturali, un linguaggio di programmazione `e costruito
su un alfabeto di simboli di base (con i quali viene scritto il programma) nella
forma di un sistema gerarchico di elementi grammaticali, tra i quali vengono
date delle relazioni (in maniera simile alle parole, frasi e affermazioni, le cui
connessioni sono date dalle regole sintattiche).
Esistono numerosi linguaggi di programmazione, tra cui `e doveroso ricordare il C, Java, il Fortran e il Prolog.
Affronteremo qui il linguaggio Pascal. La ragione di tale scelta `e eminentemente didattica.
4
4
Tipi semplici nel Pascal
Il Pascal permette l’utilizzo di un certo numero di tipi di dati di base.
Qui di seguito accenneremo ai tipi principali di dati che incontreremo nella
pratica, insieme alle operazioni e alle relazioni su di essi che il Pascal fornisce.
4.1
Tipo boolean
I dati di tipo boolean sono i valori Vero e Falso.
Il Pascal fornisce come operazioni sui booleani i connettivi logici ¬, ∧, ∨,
e le relazioni =, 6=, <, >, 6, >.
Esempio. Si ha che
¬ Vero=Falso
4.2
Falso ∧ Vero = Falso
(Falso < Vero) = Vero
Tipo char
I dati di tipo char sono i caratteri ASCII.
Ricordando che ogni carattere ASCII ha associato un corrispondente numero naturale (il suo codice), il Pascal fornisce due funzioni, Chr e Ord, la
prima delle quali associa ad un numero naturale il suo carattere corrispondente, mentre la seconda associa ad ogni carattere il suo codice.
Esempio.
Chr(63)=?
Chr(97)=a
Ord(0)=48
Ord(+)=43
5
4.3
Tipo integer
I dati di tipo integer sono gli interi tra −32768 e 32767.
Il Pascal fornisce come operazioni sugli interi +, −, ·, la divisione intera
div e la funzione resto mod.
Il Pascal fornisce sugli interi le relazioni =, 6=, <, >, 6, >.
Esempio. Valgono le seguenti
7 div 3 = 2
8 div 8 = 1
7 mod 3 = 1
8 mod 8 = 0
4.4
6 div 9 = 0
6 mod 9 = 6
Tipo real
I dati di tipo real corrispondono ad alcuni numeri reali.
Il Pascal fornisce come operazioni sui reali, tra le altre, +, −, ·, /, il valore
assoluto abs, la parte intera int, l’arrotondamento round, il quadrato sqr,
la radice quadrata sqrt, il troncamento trunc.
Il Pascal fornisce sui reali le relazioni =, 6=, <, >, 6, >.
4.5
Tipo string
I dati di tipo string sono stringhe, cio`e sequenze, di al massimo 255
caratteri ASCII.
Il Pascal fornisce come operazioni sulle stringhe, tra le altre, il +, che
permette di concatenare due stringhe, troncando ovviamente il risultato se
affiancate eccedono i 255 caratteri, e la funzione length che rende il numero
di caratteri di una stringa.
Il Pascal fornisce sulle stringhe le relazioni =, 6=, <, >, 6, >.
Esempio. pelli + cani = pellicani
6
5
Alfabeto del Pascal
Nel Pascal, l’alfabeto dei simboli di base consiste
nelle dieci cifre decimali
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
nelle lettere dell’alfabeto inglese (il Pascal non f`a differenza tra maiuscole e
minuscole)
a,
n,
b,
o,
c,
p,
d,
q,
e,
r,
f,
s,
g,
t,
h,
u,
i,
v,
j,
w,
i simboli di parentesi
( , ) , [ , ] , { , }
i simboli di punteggiatura
,
;
:
.
alcuni simboli di operazioni e relazioni logiche e aritmetiche
+ , - , * , / , = , < , >
altri simboli, come ad esempio
ˆ , $ , @ , ’ ,
k,
x,
l,
y,
m,
z,
7
6
Unit`
a lessicali in Pascal
In ogni linguaggio di programmazione, gli elementi al livello pi`
u basso,
formati da catene di simboli di base, sono chiamati lessemi o unit`
a lessicali.
Ogni lessema appartiene ad una determinata classe. Nel Pascal, le principali classi sono gli interi, i reali, le stringhe, gli operatori, gli identificatori
e le parole riservate.
6.1
Lessemi di tipo boolean
Le unit`a lessicali di tipo boolean corrispondono ai valori Vero e Falso.
Gli unici lessemi di questo tipo sono true e false.
6.2
Lessemi di tipo char
Questi lessemi corrispondono ai caratteri ASCII.
In Pascal,
• sono caratteri ASCII racchiusi da apostrofi,
• il singolo carattere apostrofo `e scritto come due apostrofi tra apostrofi.
Esempio. I seguenti sono lessemi di tipo char in Pascal
’c’
6.3
’’’’
’2’
’?’
Lessemi di tipo integer
Le unit`a lessicali di tipo integer corrispondono ai numeri interi.
Sono catene di cifre decimali, precedute o meno da uno tra i simboli + e −.
Viene richiesto che, come numeri, siano compresi tra −32768 e 32767.
Esempio. I seguenti sono interi in Pascal
0
71
-23
+107
mentre i seguenti non sono interi in Pascal
+-3
100000.
8
6.4
Lessemi di tipo real
I lessemi di tipo real corrispondono ai numeri reali.
Sono in virgola mobile, moltiplicati per una potenza intera di 10.
Sono del tipo
I.DeL
oppure
I.DEL
dove I `e un numero intero, D `e un numero naturale ed L `e un numero intero.
e, od E, equivale a 10ˆ.
D pu`o non essere presente, nel qual caso la virgola si pu`o omettere.
La parte eL, o EL, si pu`o omettere.
Viene richiesto che, come numeri positivi, siano compresi in valore assoluto
tra 2.9 · 10−39 e 1.7 · 1038 .
Esempio. I seguenti sono reali in Pascal
0
1e3
-2.3E+10
0.1e-7
mentre i seguenti non sono reali in Pascal
e3
6.5
2e100.
Lessemi di tipo string
In Pascal, le stringhe, rappresentanti testi,
• sono catene di al massimo 255 caratteri racchiuse da apostrofi,
• una stringa con niente tra gli apostrofi `e la stringa nulla,
• due apostrofi di seguito in una stringa denotano un singolo carattere, l’
apostrofo.
Esempio. I seguenti sono lessemi di tipo string in Pascal
’ciao’ ’’ ’w2+’ ’l’’Algebra’ ’Il male `
e di chi lo f`
a’
9
6.6
Operatori
In Pascal, gli operatori corrispondono a funzioni su dati. Avremo
6.6.1
Operatori booleani
Assumono valori booleani e il risultato `e di tipo booleano:
not (¬)
6.6.2
and (∧)
or (∨)
Operatori interi
Assumono valori intero e il risultato `e di tipo intero:
+
* (·)
-
6.6.3
div
mod
sqr (2 )
Operatori reali
Assumono valori reali e il risultato `e di tipo intero o reale:
6.6.4
+
-
*
/
abs
arctan
cos
exp
frac
int
ln
pi
sin
sqr
sqrt
Operatori su stringhe
Assumono valori stringhe e il risultato `e una stringa o di tipo intero:
+
length
pos
10
6.6.5
Operatori relazionali
Assumono valori di ogni tipo semplice e il risultato `e di tipo booleano:
<> (6=)
=
6.7
<
<= (6)
>
>= (>)
Identificatori
In ogni linguaggio di programmazione, gli identificatori denotano i vari
oggetti (cio`e i loro nomi) del programma che sono definiti nel programma
stesso. Principalmente, tali oggetti sono campi nei records, costanti, funzioni,
procedure, programmi, tipi, unit`a, variabili.
In Pascal,
• gli identificatori sono catene di caratteri di qualsiasi lunghezza, ma solo i
primi 63 caratteri sono significativi,
• il primo carattere deve essere una lettera,
• i successivi caratteri possono essere lettere, cifre decimali, o il simbolo .
Esempio. I seguenti sono identificatori in Pascal
x
a1
yy
punto medio
delta
I seguenti non sono identificatori in Pascal
2x
x y
6.8
Parole riservate
po’
lealt`
a
a@b
In ogni linguaggio di programmazione, alcuni identificatori sono definiti
dal linguaggio stesso. Tali identificatori prendono il nome di parole riservate.
Nel Pascal, le principali parole riservate sono:
11
and
array
begin
case
const
div
do
downto
else
end
for
function
if
mod
not
of
or
procedure
program
repeat
then
to
until
uses
var
while
12
7
Strutture di base in Pascal
I livelli successivi di elementi di un linguaggio di programmazione.
Sono essenzialmente di tre tipi: espressioni, dichiarazioni, istruzioni.
7.1
Espressioni
Le espressioni sono sorgenti di valori, ottenute a partire da operatori
e operandi.
Gli operandi sono principalmente costanti, variabili e chiamate di funzioni, eventualmente usando le parentesi tonde.
Esempio. Espressioni intere:
n+1
(2*y) mod 3
lenght(x)-int(3.2)
Espressioni booleane:
i < 3
7.2
ord(’x’) <= ord(’y’)
sqr(b) = 4*a*c
Dichiarazioni
Le dichiarazioni sono sorgenti di informazione assegnate all’occorrenza
che definisce il lessema.
Essenzialmente, decrivono la tipologia di valori calcolati dall’esecuzione
del programma, la loro rappresentazione e il modo in cui vengono immagazzinati nella memoria del computer.
Per valori composti come gli array (vettori, matrici) e valori strutturati
(record) viene specificato anche il modo di accedere ai suoi componenti elementari.
13
7.2.1
Dichiarazioni di costanti
Una dichiarazione di costante definisce un identificatore come una
costante di un determinato tipo.
La sintassi `e:
const identificatore = espressione ;
identificatore = espressione ;
...
Esempio.
const base = 10 ;
e = 2.71828 ;
7.2.2
Dichiarazioni di variabili
Una dichiarazione di variabile definisce un identificatore come una
variabile di un determinato tipo.
La sintassi `e:
var
identificatore : tipo ;
identificatore , identificatore :
...
Esempio.
var n , m : integer ;
x , y , z : real ;
nome : string ;
tipo ;
14
7.3
Istruzioni
Le istruzioni, o affermazioni, sono unit`a di operazioni finite nel programma; le istruzioni di base sono principalmente gli assegnamenti, le chiamate di procedure, le istruzioni begin...end, le istruzioni condizionali, le
istruzioni iterative e le istruzioni ricorsive.
7.3.1
Assegnamenti
Un assegnamento attribuisce il valore di un’espressione ad una variabile.
La sintassi `e:
identificatore := espressione ;
Esempio.
area := b*h ;
i := i+1 ;
alfa := beta and gamma ;
7.3.2
Chiamate di procedure
La definizione di una procedura introduce una notazione abbreviata e
parametrizzata per la funzione di una certa parte del programma (il corpo
della procedura). L’esecuzione del corpo della procedura pu`o essere conseguentemente trattata come un’operazione elementare causata da una chiamata della procedura.
Il Pascal fornisce alcune procedure. Qui mi preme considerare il write e
il read (per le altre, `e sufficiente accedere all’ottimo help del Turbo Pascal).
La procedura write scrive sul monitor le espressioni Oi di tipo semplice. La procedura writeln, inoltre, porta il cursore all’inizio della riga
successiva. Le sintassi:
write(O1) ;
write(O1,O2) ;
...
15
La procedura read legge da tastiera uno o pi`
u valori e li associa alle
variabili Vi. La procedura readln, inoltre, salta alla linea successiva. Le
sintassi:
read(V1) ;
read(V1,V2) ;
...
7.3.3
Istruzioni begin ... end
` un’istruzione composta. In questo modo, tutte le istruzioni comprese
E
tra le parole riservate begin ed end (da intendersi come semplici parentesi),
vengono trattate come un’unica istruzione.
La sintassi `e:
begin
istruzione ;
istruzione ;
...
istruzione
end ;
7.3.4
Istruzioni condizionali
In un’istruzione condizionale, la scelta tra una o pi`
u istruzioni dipende
dal verificarsi o meno di una condizione (espressione booleana).
In Pascal, abbiamo le istruzioni if e case:
Per la prima, la sintassi `e:
if espressione then istruzione ;
oppure
if espressione then istruzione else istruzione ;
16
Se la condizione dopo l’if `e verificata, viene eseguita l’istruzione dopo il
then, altrimenti, nel secondo caso, viene eseguita l’istruzione dopo l’else.
Esempio.
if abs(n) < 10
then writeln(n,’ ha un’’unica cifra’)
else writeln(n,’ ha almeno due cifre’);
Per la seconda, la sintassi `e:
case espressione of
case : istruzione ;
...
case : istruzione ;
end ;
oppure
case espressione of
case : istruzione ;
...
case : istruzione ;
else
istruzione
end ;
In questa istruzione, il valore dell’espressione seleziona l’istruzione corrispondente.
Esempio.
case n mod 2 of
` pari’) ;
0 : writeln(n,’ e
1 : writeln(n,’ `
e dispari’) ;
end ;
7.3.5
Istruzioni iterative
Un’istruzione iterativa ripete un numero fissato di volte (itera) una
certa parte del programma (il corpo dell’iterazione).
In Pascal, abbiamo l’istruzione for, la cui sintassi `e:
17
for var := primo to ultimo do istruzione ;
oppure
for var := primo downto ultimo do istruzione ;
Esempio. for i:=1 to 10 do writeln(i*i) ;
7.3.6
Istruzioni ricorsive
Un’istruzione ricorsiva dispone un’esecuzione ripetitiva di una certa
parte del programma (il corpo della ricorsione), dove il numero delle ripetizioni `e determinato da una data condizione.
In Pascal, abbiamo le istruzioni while e repeat:
Per la prima, la sintassi `e:
while espressione do istruzione ;
L’istruzione dopo il do viene ripetuta fintanto che l’espressione rimane
vera.
Si noti che se l’espressione `e inizialmente falsa, l’istruzione non viene
eseguita.
Esempio.
i:=2 ;
while (n mod i) <> 0 do i:=i+1 ;
if i = n
then writeln(n,’ `
e primo’)
else writeln(n,’ `
e composto’);
Per la seconda, la sintassi `e:
repeat
istruzione ;
istruzione ;
...
istruzione
until espressione ;
18
Le istruzioni comprese tra il repeat e l’until vengono eseguite fintanto
che l’espressione risulta falsa. Quando l’espressione diventa vera, si esce dal
ciclo.
Si noti che tali istruzioni vengono eseguite almeno una volta.
Esempio. : repeat readln(s) until (s=’m’) or (s=’f’) ;
19
8
Struttura di un programma
Un programma in Turbo Pascal pu`o avere il seguente aspetto
program identificatore ;
uses ... ;
const ... ;
type ... ;
var ... ;
procedure ... ;
function ... ;
begin
istruzione ;
...
end.
Esempio. Ecco il vostro primo programma:
program pippo ;
begin
writeln(’Ciao mondo!’)
end.
La clausola uses nomina le unit`a (librerie) utilizzate dal programma.
la clausola type permette di definire nuovi tipi.
Le clausole procedure e function permettono di definire nuove funzioni e procedure.
Esempio. Le seguenti producono la stessa funzione potenza:
function potenza(x , n : integer): integer;
begin
if n=0
then potenza:= 1
else potenza:= x ∗ potenza(x,n-1)
end
20
function potenza(x , n : integer): integer;
var i, p: integer;
begin
p:= 1 ;
for i:= 1 to n do p:= p ∗ x ;
potenza:= p
end