Il linguaggio C

Transcript

Il linguaggio C
A. DE SANTIS – M. CACCIAGLIA – C. SAGGESE
IL TURBO PASCAL
Premessa
Il linguaggio Pascal, creato essenzialmente per scopi didattici nel 1974, è un linguaggio di tipo
compilato, ad alto livello, particolarmente adatto per lo sviluppo della programmazione strutturata.
Nel 1983 è stato definito, per tale linguaggio, uno standard ANSI e sempre nello stesso anno dalla
Borland International fu presentato un compilatore Pascal, denominato TURBO-PASCAL, che
possedeva caratteristiche del tutto innovative, rispetto ai compilatori presenti in commercio. Esso, in un
unico ambiente integrato, associava un editore, per la scrittura del programma, un compilatore veloce e
potente ed un debugger per gli errori, integrato con l'editore stesso.
In seguito il TURBO-PASCAL (TP) è stato migliorato, apportando modifiche alle successive versioni, a
volte, anche sostanziali. Il Pascal della Borland presenta anche alcune differenze rispetto al linguaggio
standard.
Per la stesura e la prova dei programmi presenti in questa trattazione (di cui è possibile scaricare
direttamente i sorgenti), si può anche utilizzare la versione DEV-PASCAL distribuito con licenza GPL
(General Public License), reperibile sul sito http://www.bloodshed.net/ che opera anche in ambiente
Windows XP.
Utilizzando DEV-PASCAL per evitare che, terminato il programma, si ritorni immediatamente in ambiente
Windows, senza quindi permettere la visualizzazone dei risultati, si deve aggiungere al termine del
programma una riga con l’istruzione Readln(); (seguita dal punto e virgola) prima dell’end finale. Il
programma, prima che sia posto in esecuzione, deve essere salvato con SAVE UNIT AS … .
Si ritorna nell’ambiente del sistema operativo con INVIO. Per avviare il programma si usa il pulsante RUN
PROJECT o COMPILE AND RUN PROJECT se al sorgente sono state apportate delle modifiche.
I file che utilizzano modalità grafiche per essere posti in esecuzione con DEV-PASCAL
necessitano di alcune modifiche descritte al termine del paragrafo che tratta dei metodi grafici in
TP.
1 L’ambiente dell’editore in TP
Essendo il Pascal un linguaggio compilato, il programmatore deve, come prima cosa, scrivere le
istruzioni che costituiscono il programma utilizzando un editore di testi. Quanto scritto viene poi salvato in
un file su disco (detto file sorgente) assegnandogli un nome con estensione ".PAS" (per esempio
PROGRAM1.PAS).
Il file sorgente è compilato per mezzo del compilatore e trasformato prima nel file oggetto (con
estensione ".OBJ") e poi, con il linker, ulteriormente tradotto in un file eseguibile (con estensione
".EXE").
Nel TURBO-PASCAL, le funzioni di editore e di linker, sono integrate direttamente nel compilatore e,
pertanto, il procedimento di compilazione per ottenere la copia eseguibile è del tutto automatico.
Una volta avviato il programma [1] si entra direttamente nell’ambiente dell’editor e sul video appare il
menu principale. Sulla parte alta sono visualizzati una serie di comandi su cui ci si può posizionare
direttamente, servendosi del mouse o digitando ALT e contemporaneamente la prima lettera del comando
desiderato.
______________
[1]
Per lanciare il programma ci si deve porre entro la directory contenente il file TURBO.EXE e digitato TURBO dare invio.
Normalmente esso si trova entro la subdirectory BIN che è, a sua volta, subdirecory di TP. Quindi il percorso completo per
raggiungere il file è C:\TP\BIN\TURBO.EXE, supponendo che esso si trovi sul disco C:. Per evitare di cambiare ogni volta directory
si può inserire il percorso di ricerca nella PATH del file AUTOEXEC.BAT
________________
Compare in questo modo un menu a tendina con vari sottocomandi. Per eseguire un sottocomando si
posiziona la barra evidenziatrice sulla voce desiderata con i tasti cursore (↓ o ) e si dà INVIO (oppure con
il mouse si fa clic con il pulsante sinistro). Ci si può anche spostare da un comando all’altro sempre con i
tasti cursore (← →) o con il mouse.
Si esce dai vari menu digitando ESC.
I comandi del menu principale visualizzati sul video in alto sono:
File
Edit
Search
Run
Compile
Debug
Tools
Options
Window
Help
Come già detto, da ognuno di essi si ottiene un sottomenu a tendina che presenta una serie di possibili
scelte.
Senza entrare nei dettagli circa l’uso dei singoli comandi [2] (per questo si rinvia il lettore all’uso del
manuale del TURBO-PASCAL comunque, per i comandi è fornita, di volta in volta, una breve
spiegazione nella riga sul fondo dello schermo), al fine di orientare il programmatore, si procede passo
passo alla stesura di un semplice programma, alla sua compilazione e alla sua esecuzione. In tal modo
sarà possibile comprendere rapidamente i procedimenti essenziali che dovranno essere eseguiti
anche nel seguito, per allestire altri programmi.
Entrati nell’ambiente dell’editor, compare in alto a sinistra, sotto la barra dei comandi, un trattino
lampeggiante che rappresenta il cursore, in altre parole il punto in cui sarà inserito il carattere digitato. Il
cursore si sposta in avanti man mano che si scrive del testo. Si digiti il seguente programma, senza
tenere conto, per il momento, del significato delle varie istruzioni:
Prog. 1- Programma iniziale
program proviniz;
var
nome,citt : string[20];
begin
writeln;
writeln (’ digita da tastiera il tuo nome e poi dai invio’);
readln (nome);
writeln (’ digita da tastiera il nome della tua città ’ e poi dai invio’);
readln (citt);
writeln;
write
(’ il tuo nome è ’,nome);
writeln (’ e sei di ’,citt);
end.
Al termine di ogni riga bisogna dare invio per passare alla riga successiva. Si faccia bene attenzione a
mettere i punti e virgola (;) alla fine delle istruzioni, dove sono presenti, e il punto (.) dopo l’end finale.
Terminata la scrittura del programma è bene controllare che il testo digitato sia identico al testo sopra
riportato, per non incorrere in errori e solo dopo procedere all’esecuzione.
E’ buona norma, prima di effettuare le suddette operazioni, salvare sul disco il programma scritto. A tale
scopo si attivi il menu relativo al comando FILE (con ALT-F o con il mouse), e si faccia clic sul comando
SAVE AS ... . Comparirà una nuova finestra e, a partire dalla posizione del cursore, va inserito il nome del
file con il relativo percorso; inseriti i dati, dare di nuovo INVIO. Si supponga di voler salvare il programma
con il nome PRO3_2_1.PAS, sulla cartella PASCAL creata sul disco C:, si dovrà scrivere:
C:\PASCAL\PRO3_2_1 ↵
Non è necessario inserire l’estensione “.PAS” poiché sarà messa automaticamente dall’editore durante il
salvataggio su disco.
Avvenuta la scrittura del file, viene nuovamente visualizzato lo schermo dell’editor. Selezionare il
comando COMPILE (con ALT-C) e sulla voce del menu a tendina COMPILE (la prima in alto), dare invio.
Verrà eseguita la compilazione del programma e, se non vengono riscontrati errori di sintassi, comparirà
una finestra in cui sarà visualizzato un messaggio che avvertirà l’operatore del successo dell’operazione.
Digitando un tasto qualsiasi si ritorna all’editor.
In caso fossero riscontrati degli errori, la compilazione non sarà ultimata e avverrà un ritorno direttamente
all’editor; prima di procedere ad una nuova compilazione, andranno corretti gli errori riscontrati.
Per avviare il programma selezionare il comando RUN dal menu principale e fare clic sulla prima voce
RUN del menu a tendina. In alternativa si può porre in esecuzione il programma con l’uso contemporaneo
dei tasti CTRL-F9.
Il programma si avvierà, scomparirà il video dell’editor e comparirà quello relativo all’ambiente dell’utente.
Nel caso presente, verrà visualizzato il messaggio di richiesta del proprio nome. Questo dovrà essere
digitato da tastiera e dovrà darsi poi INVIO. La stessa operazione andrà eseguita anche dopo la comparsa
del secondo messaggio. Il programma seguiterà a svolgere le proprie funzioni visualizzando un terzo
messaggio, che però scomparirà rapidamente poiché avviene un ritorno automatico all’ambiente
dell’editore.
Per tornare allo schermo utente e visualizzare quanto è stato scritto si digita ALT-F5. Si rientra nell’editor
premendo un tasto qualsiasi.
Infine, andrà salvato di nuovo il file sorgente utilizzando questa volta il comando SAVE del menu File (o
semplicemente utilizzando il tasto funzione F2). Non serve immettere di nuovo il nome del file perchè è
stato fatto la prima volta con SAVE AS ... .
Si esce dal TURBO-PASCAL con ALT-X (o dal comando EXIT del menu relativo a FILE).
2 Tipi di dati
In un programma vengono generalmente elaborate alcune grandezze di tipo numerico o alfanumerico per
ottenere dei risultati. Tali grandezze sono raggruppate in particolari categorie, dette tipi di dati. Esse
rappresentano le varietà di dati primari, disponibili per il programmatore, che il linguaggio è in grado di
gestire.
Nello svolgimento di un programma si deve poter immettere nel sistema dei dati (input) e poi estrarre da
esso le informazioni ottenute, elaborando opportunamente i dati immessi (output).
I dati da utilizzare vengono memorizzati nel sistema con opportuni identificatori ovvero dei nomi
convenzionali attribuiti ai dati stessi. Se tali identificatori sono assegnati a dati soggetti a variazioni di
valore nel corso del programma, sono definiti variabili e in caso contrario costanti.
All'inizio di un programma in Pascal è sempre necessario fare un elenco con i nomi delle variabili e
delle costanti che verranno utilizzate nel seguito (dichiarazione delle variabili e delle costanti). La
dichiarazione delle variabili viene fatta precedere dalla parola riservata Var e quella delle costanti da
Const.
Nel Pascal per attribuire ad un certo dato il relativo identificatore si utilizza il simbolo di assegnazione " :=
" (due punti seguiti dall'uguale senza alcuno spazio interposto tra i due caratteri). Tale simbolo sta ad
indicare che il valore di quanto è scritto a destra viene assegnato all’identificatore posto a sinistra (in
genere l'identificatore di una variabile o di una costante).
Esempio :
pigreco := 3.1415;
carattere := 'A';
somma := a + b
In questi esempi all'identificatore pigreco viene attribuito il valore costante 3.1415; all'identificatore
carattere il valore, sempre costante, della lettera A e, infine, a somma il valore variabile della somma di
a e b. In questo caso a e b rappresentano gli identificatori di due dati, che possono assumere, nel corso
del programma, valori diversi.
Una prima suddivisione dei dati presenti nel TURBO-PASCAL può essere fatta tra i tipi semplici
(integer, boolean, char, real), i tipi strutturati (array, record, set, file), il tipo
puntatore e il tipo stringa.
I tipi semplici, con l’esclusione dei real, sono di tipo ordinale [3].
_____________________
[3]
Sono definiti ordinali quei tipi di dati che formano un insieme ordinato di elementi. Al primo elemento di un tipo ordinale viene
assegnato valore 0, al secondo 1 e così via. Fanno eccezione a tale regola gli interi per i quali vanno presi in considerazione anche
i
valori
negativi.
________________________
Vengono ora analizzati più in dettaglio tali tipi di dati, che possono considerarsi nel TURBO-PASCAL,
come dati standard, in altre parole predefiniti.
Integer
Numeri interi senza virgola.
Possono essere distinti in cinque sottogruppi (nel Pascal standard è presente solo l’integer):
Tab. 1
tipo
byte
shortint
integer
word
longint
da
a
0
-128
-32768
0
2.147.483.64
8
255
127
32767
65535
2.147.483.647
numero
byte
1
1
2
2
4
Esempi di numeri interi di tipo integer:
num1 = 312; num2 = -342; num3 = 32767
Real
Numeri reali in virgola mobile.
Possono essere distinti in quattro sottogruppi (nel Pascal standard è presente solo il real):
Tab. 2
tipo
real
single
double
da
a
2.9 x 10-38
1.5 x 10-45
5.0 x 10-
1.7 x 1038
3.4 x 1038
1.7 x 10308
1.9 x 10-
1.1 x
104932
324
extended
4951
numero
byte
6
4
8
10
Esempi di numeri di tipo real:
num1: = 3.14; num2 := 4.0; num3:= -34.2 ; num4:= 2.767 E − 5.
Con l'ultimo esempio si è utilizzato un altro metodo per rappresentare i numeri reali: la lettera E seguita
da un numero corrisponde alla forma esponenziale ed equivale a "dieci elevato a ..." (nel caso
precedente E − 5 = 10-5).
Char
Caratteri.
Char singolo carattere (lettera alfabetica, cifra numerica da 0 a 9, segno d'interpunzione o qualsiasi altro
simbolo rappresentabile con il PC).
Esempi di char:
alfa := 'a'
;
carattere := '3'
;
car := '*' ; alfa2 := 'A' .
Come si vede i caratteri vanno racchiusi tra due apici semplici.
Boolean
Tipo booleano.
I tipi boolean possono assumere solo due valori vero (true) o falso (false).
Oltre che assegnare i valori booleani a delle variabili o costanti è possibile utilizzare tale tipo di dato in
espressioni particolari dette booleane che possono dare come risultato un valore vero o falso. Tali
espressioni saranno esaminate nel seguito.
Esempi di dati boolean:
rosso := true
;
verde := false.
String
Tipo stringa.
Il tipo string è formato da un insieme di caratteri (non presente nel Pascal standard).
Esempi di string:
nome := 'Marco'
;
data := '12/3/92'
;
string1 := '24
E−10' .
Anche le stringhe vanno racchiuse tra apici semplici.
Pointer
Tipo puntatore.
Si differenzia dai precedenti perché non rappresenta direttamente un dato ma il suo indirizzo. Quindi una
variabile di tipo puntatore contiene l’indirizzo di una locazione di memoria in cui è memorizzato un dato
(→ Paragrafo 17).
Tipi strutturati.
tipo Array
•
tipo Record
•
tipo Set
•
•
tipo File.
Sono tipi di dati che presentano una configurazione più complessa rispetto a quelli finora descritti. Essi
verranno esaminati nel paragrafo 11.
Il Pascal mette inoltre a disposizione del programmatore la possibilità di definire tipi di dati diversi da
quelli predefiniti, secondo le proprie esigenze. Tale definizione viene effettuata utilizzando la parola
riservata type.
La definizione di tipo viene effettuata prima di quella delle variabili, come è messo in evidenza
nell'esempio seguente.
Esempio
Type giorno = (lunedì, martedì, mercoledì, giovedì, venerdì, sabato, domenica);
colore = (rosso, giallo, verde);
secondi = 0..59;
Var domani : giorno;
vernice :colore;
tempo = secondi.
Nell'esempio sono stati definiti come nuovi tipi di dati giorno, colore, e secondi. Per ognuno di essi
sono stati elencati gli elementi appartenenti al dato tipo; così al tipo giorno appartengono tutti i giorni
della settimana, al tipo colore i colori rosso, giallo e verde e al tipo secondi i numeri interi da 0 a 59.
Nel caso dei secondi il simbolo ".." (due punti) separa il minimo valore dell'insieme definito da quello
massimo.
La dichiarazione successiva di variabile (Var), indica che all'identificatore domani potrà essere attribuito,
nel corso del programma, solo uno dei valori tipo giorno. E così negli altri casi.
I tipi di dati precedentemente definiti sono del tipo ordinale perché costituiscono un insieme ordinato [4].
Ad ognuno di essi è associato un valore intero a partire dallo zero. Così, per esempio, lunedì avrà
valore 0, martedì valore 1, e così via.
___________________
[4]
I tipi ordinali vengono in genere distinti in enumerativi, come per esempio colore = (rosso, giallo, verde), e in subrange (o
sottocampo) come per esempio secondi = 0..59. Nei tipi subrange sono assegnati i valori inferiore (0) e superiore (59) di un
certo
intervallo
di
valori.
______________________
3 Readln e writeln
Si è detto che in un programma è fondamentale avere la possibilità di immettere dati per l'elaborazione e
poi di esaminarne i risultati.
Nel Pascal tali operazioni vengono realizzate attraverso delle procedure predefinite, presenti all'interno
del compilatore stesso (una procedura è un programma che viene chiamato da un altro programma).
Le procedure più comunemente utilizzate per immettere dati dalla tastiera sono:
• readln (num): quando, nel corso dello svolgimento di un programma, si incontra la procedura
readln (num), il sistema si arresta e rimane in attesa che venga immesso un dato il cui valore
viene assegnato alla variabile individuata dall’identificatore num. Il tipo di dato che viene
introdotto dalla tastiera deve essere compatibile con il tipo che si è assegnato alla variabile num
all'inizio del programma. La chiamata alla suddetta procedura, inserisce un ritorno a capo
automatico.
• read (num): in tal caso non viene inserito il ritorno a capo dopo la chiamata della procedura.
Per visualizzare invece i risultati di un’elaborazione si utilizza la seguente procedura:
• writeln (alfa): in questo caso viene visualizzato sul video il valore che ha la variabile alfa al
momento della chiamata della funzione. Anche in questo caso viene inserito un ritorno a capo e
quindi eventuali altri dati verranno visualizzati nella riga successiva.
Per non effettuare il salto di riga si usa:
• write (alfa).
4 Struttura di un programma
Scrivendo un programma in Pascal si deve rispettare una precisa sequenza nel disporre le varie parti che
lo compongono. È esposta di seguito la successione da assegnare alle varie parti, con evidenziate le
parole chiave (in grassetto) adoperate per le varie dichiarazioni:
program nome_del _programma;
const
dichiarazione delle costanti;
type
definizione dei tipi di dati diversi da quelli predefiniti;
var
dichiarazione delle variabili;
procedure nome_procedura (lista parametri);
dichiarazione costanti, tipi e variabili per la procedura
begin
istruzioni della procedura
end;
function
nome_funzione (lista parametri) : tipo_funzione;
dichiarazione costanti, tipi e variabili per la funzione
........begin
istruzioni della funzione
end;
begin
end.
istruzioni del programma principale;
Le procedure e le funzioni sono dei sottoprogrammi che possono essere chiamati (e quindi fatti
eseguire) da un punto qualsiasi del programma principale. Non sempre sono presenti in ogni programma.
La loro struttura verrà esaminata in seguito.
5 Gli operatori
Esaminata la struttura di un programma, si esamini ora con quali mezzi possono essere opportunamente
elaborati i dati immessi.
Il Pascal per tale scopo utilizza una serie di operatori che possiamo suddividere in varie classi in base
alla loro specifica funzione.
Operatore di assegnazione
Il simbolo di assegnazione è formato dai due punti seguiti dal segno uguale ( := ).
Modo di operare: destinazione := sorgente
Esempi:
A:=3 (ad A viene assegnato il valore 3);
B:= B+1 (a B viene assegnato il vecchio valore di B aumentato di uno).
Operatori aritmetici
Effettuano le classiche operazioni aritmetiche operando su dati di tipo intero e reale:
Tab. 3
Tipo
operazione
Somma
Sottrazione
Divisione
Modulo
di
Divisione
Moltiplicazione
Operatore
Tipi di dato
+
div
mod
interi o reali
interi o reali
interi
interi
/
*
interi o reali
interi o reali
quoziente intero
resto divisione tra
interi
Esempi:
quoz := 11 div 3 (a quoz viene assegnato il valore 3 quoziente della divisione senza
virgola;
quoz
deve
essere dichiarato intero);
resto := 11 mod 3 (a resto viene assegnato il valore 2 ovvero il resto della divisione;
resto
deve
essere dichiarato intero);
quoz := 11/3 (a quoz viene assegnato il valore 3.66... quoziente della divisione tra due interi
con
risultato
reale;
quoz deve essere dichiarato reale).
Operatori sui bit
Possono operare sui tipi interi effettuando manipolazione a livello di singolo bit:
Tab. 4
Tipo di
operazione
and
or
or esclusivo
not
shift
sinistra
shift
destra
Operatore
and
or
or
a
not
shl
a
shr
Operazione effettuata
Esegue la and tra i bit corrispondenti di due interi.
Esegue la or tra i bit corrispondenti di due interi.
Esegue un or esclusivo tra i bit corrispondenti di due
interi.
Esegue la not su ogni bit di un intero.
Sposta a sinistra i bit di un intero, inserendo a destra
degli zeri.
Sposta a destra i bit di un intero, inserendo a sinistra
degli zeri.
Esempi:
Si supponga che i numeri utilizzati siano tutti di tipo byte (appartenenti agli interi).
num1 := 3 ; num2 := 5 ; num3 := num1 and num2 ;
• a num3 viene assegnato il risultato1; infatti se scriviamo i numeri in binario e si esegue la
and bit a bit si ha:
num1 = 0000 0011
num2 = 0000 0101
num3 = 0000 0001
• num1 := 15; num2 := not
num1; a num2 viene attribuito il risultato 240; infatti
scrivendo in binario i numeri e negando bit a bit si ha:
num1 = 0000 1111
num2 = 1111 0000
• num1 := 243 ; num2 := num1 shr 1; a num2 viene assegnato il valore 121; l'uno
dopo l'istruzione shr indica che viene effettuato un solo scorrimento. Scrivendo num1
in binario, traslando ogni suo bit a destra di una posizione e immettendo uno zero
all'inizio si ha:
num1 = 1111 0011
\ \ \ \
num2 = 0111 1001
\ \ \
il bit meno significativo (ultimo a destra) di num1 viene perso.
Operatori logici
Tali operatori restituiscono come risultato sempre un valore vero o uno falso. Operano quindi soltanto su
dati di tipo boolean che sono veri (true) o falsi (false). Essi possono restituire solo due valori: vero o falso.
Non sono da confondere con gli operatori precedenti che invece possono restituire qualsiasi valore.
Tab. 5
Tipo di
operazione
and
Operatore
and
or
or
or esclusivo
xor
not
not
Operazione effettuata
Esegue la and tra due dati di tipo boolean, il risultato è
vero solo se sono veri ambedue i dati.
Esegue la or tra due dati di tipo boolean, il risultato è
vero se almeno uno dei due dati è vero.
Esegue un or esclusivo tra due dati di tipo boolean, il
risultato è vero se i due dati sono uno falso e l'altro vero
o viceversa.
Esegue la not su un dato di tipo boolean, il risultato è
vero se il dato è falso e viceversa.
Esempi:
•
•
A := true; B := false; C := A and B (C avrà un valore falso);
A := true; B := false; C := A or B (C avrà un valore vero ).
Operatori relazionali
Operano un confronto tra due dati che possono essere del tipo intero, reale, carattere o stringa. Nel caso
di tipi intero o reale i due dati confrontati possono essere anche non essere dello stesso tipo. Negli altri
casi invece i tipi confrontati devono coincidere. Il risultato del confronto è sempre boolean.
Tab. 6
Tipo
di
operazione
uguale
diverso
maggiore
minore
maggiore
o
uguale
minore o uguale
Simbolo
Operazione effettuata
=
< >
>
<
> =
Confronta l'eguaglianza tra due dati.
Controlla se un dato è diverso dall'altro.
Controlla se un dato è maggiore dell'altro.
Controlla se un dato è minore dell'altro.
Controlla se un dato è maggiore o uguale all'altro.
< =
Controlla se un dato è minore o uguale all'altro.
Esempi:
•
•
•
num1 := 4 ; num2 := 5 ; num1 =
num1 < num2 restituisce falso (false);
num1 > num2 restituisce vero (true).
num2 restituisce falso (false);
Quando gli operatori relazionali agiscono su delle stringhe nel confronto vengono considerati i codici ASCII dei
singoli caratteri inclusi gli spazi.
Operatore stringa
E' un operatore che permette di concatenare due stringhe formandone una sola. Se la stringa risultante
dalla concatenazione è più lunga di 255 caratteri, essa viene troncata. Il simbolo che rappresenta tale
operatore è il segno più (+).
Esempio:
nome := ‘Mario ’ + ‘ Rossi’; all’identificatore nome è assegnata la stringa concatenata
‘Mario Rossi’.
5.1 - Programmi di applicazione sugli operatori
Vengono ora svolti alcuni semplici programmi di esempio che utilizzano le nozioni sopra esposte. In
PASCAL i commenti vengono racchiusi tra due coppie di parentesi tonde e due asterischi (*…
commento …*), oppure tra due coppie di parentesi graffe {… commento …}.
Prog. 2 - Programma con operatori aritmetici
(*programma che utilizza le procedure readln e writeln, dichiara delle
costanti e delle variabili intere, effettua operazioni aritmetiche
e poi visualizza i risultati su video*)
program uso_oper_aritm;
(*DICHIARAZIONE DELLE COSTANTI E DELLE VARIABILI*)
const
num1 = 11 ;
num2 = 3 ;
var
resto, quoz,divid
:integer;
(*INIZIO PROGRAMMA PRINCIPALE*)
begin
writeln ;
writeln ('
DIVISIONE TRA NUMERI INTERI ');
quoz := num1 div num2;
writeln ('IL QUOZIENTE DELLA DIVISIONE TRA 11 E 3 E'': ');
writeln (' QUOZIENTE = ',quoz);
resto := num1 mod num2;
writeln ('IL RESTO DELLA DIVISIONE TRA 11 E 3 E'': ');
writeln (' RESTO = ',resto);
writeln ('CONTROLLO DEL RISULTATO ');
writeln ('quoziente x divisore + resto = dividendo ');
divid := quoz * num2 + resto ;
writeln (' DIVIDENDO = ',divid);
end.
Prog. 3 - Programma con operatori aritmetici
(*programma che utilizza le procedure readln e writeln, dichiara delle
costanti INTERE e delle variabili REALI, effettua la divisione tra
gli interi e poi visualizza i risultati su video*)
program reali;
(*DICHIARAZIONE DELLE COSTANTI E DELLE VARIABILI*)
const
num1 = 11 ;
num2 = 3 ;
var
quoz
:real;
(*INIZIO PROGRAMMA PRINCIPALE*)
begin
writeln ;
writeln ('
DIVISIONE TRA NUMERI INTERI CON RISULTATO REALE');
writeln ;
quoz := num1 / num2;
writeln ('IL QUOZIENTE DELLA DIVISIONE TRA 11 E 3 E'': ');
writeln (' QUOZIENTE = ',quoz);
end.
Prog. 4 - Programma con operatori sui BIT (and)
(*programma che utilizza la procedura writeln, dichiara delle
costanti INTERE e delle variabili INTERE, effettua operazioni sui
bit e poi visualizza i risultati su video*)
program operandi_su_bit_1;
(*DICHIARAZIONE DELLE COSTANTI E DELLE VARIABILI*)
const
num1 = 3 ;
num2 = 5 ;
var
num3
:integer;
(*INIZIO PROGRAMMA PRINCIPALE*)
begin
writeln ;
writeln (' OPERAZIONI SUI BIT DI NUMERI INTERI CON RISULTATO INTERO');
writeln ;
num3 := num1 and num2;
writeln ('IL RISULTATO DELLA AND TRA 11 E 5 E'': ',num3);
end.
Prog. 5 - Programma con operatori sui BIT (and)
(*programma che utilizza la procedura writeln, dichiara delle
costanti INTERE e delle variabili INTERE, effettua operazioni sui
bit e poi visualizza i risultati su video*)
program operandi_su_bit_2;
(*DICHIARAZIONE DELLE VARIABILI*)
var
num1, num2
: byte;
(*PROGRAMMA PRINCIPALE*)
begin
num1:=15;
writeln ;
writeln (' OPERAZIONI SUI BIT DI NUMERI INTERI CON RISULTATO INTERO');
writeln ;
num2 := not num1
;
writeln ('IL RISULTATO DELLA NOT SUL NUMERO 15 E'': ',num2);
end.
Prog. 6 - Programma con operatori sui BIT (shift)
(*programma che utilizza la procedura writeln, dichiara delle
costanti INTERE e delle variabili INTERE, effettua operazioni sui
bit e poi visualizza i risultati su video*)
program operandi_su_bit_3;
(*DICHIARAZIONE DELLE VARIABILI*)
var
num1, num2
: byte;
(*INIZIO PROGRAMMA PRINCIPALE*)
begin
num1:=243;
writeln ;
writeln (' OPERAZIONI SUI BIT DI NUMERI INTERI CON RISULTATO INTERO');
writeln ;
num2 := num1 shr 1 ;
(*effettua un solo shift*)
writeln ('IL RISULTATO DELLO SHIFT A DESTRA SUL NUMERO 243 E'': ',num2);
end.
Prog. 7 - Programma con specificatori dell’ampiezza del campo
(*programma che utilizza le procedure writeln e readln, calcola la potenza
dissipata su un resistore e la differenza di potenziale ai suoi capi
assegnato il suo valore e la corrente che lo attraversa*)
program potenza;
(*DICHIARAZIONE DELLE VARIABILI*)
var
res, corr, pot, tens
: real;
(*INIZIO PROGRAMMA PRINCIPALE*)
begin
writeln ;
writeln ('
CALCOLO DELLA POTENZA DISSIPATA SU UN RESISTORE');
writeln ;
write
('INTRODUCI IL VALORE DEL RESISTORE [Ω] ');
readln (res);
write
('INTRODUCI IL VALORE DELLA CORRENTE [A] ');
readln (corr);
pot := res * ( corr * corr );
tens := res * corr ;
writeln ;
writeln ('LA POTENZA DISSIPATA SUL RESISTORE E'': ',pot:4:3, ' [W]');
writeln ('LA TENSIONE AI SUOI CAPI E''
: ',tens:4:3, ' [V]');
writeln ;
•
•
•
Note:
Nel Programma 7 e in altri che seguono si incontrano caratteri dell’alfabeto greco e altri simboli non
presenti sulla tastiera. Essi vanno inseriti tenendo premuto il tasto ALT e digitando contemporaneamente
il codice ASCII del carattere da inserire, utilizzando la tastiera numerica. Questo codice è legato alla
tabella codici inizializzata all’atto dell’accensione del computer. Perché ci sia corrispondenza tra i simboli
da visualizzare ed i codici digitati, la tabella caricata con AUTOEXEC.BAT, deve essere la 437 (e non la
850). Alcuni dei codici usati sono: Ω = ALT 234 ,π = ALT 227, τ = ALT 231, µ = ALT 230, √ = ALT 251.
Nelle istruzioni writeln sono state poste dopo le variabili pot e tens da visualizzare due punti (:)
seguiti da dei numeri. Essi rappresentano gli specificatori dell’ampiezza di campo.
Nei due casi presenti nel Programma 7, il campo totale indicato (4 cifre), è più piccolo di quello effettivo,
quindi esso viene espanso al minimo necessario. Le cifre decimali stampate invece sono esattamente
tre, in altre parole quante ne sono state indicate.
Tale modalità di scrittura delle variabili, deve essere usata ogni volta che si desidera visualizzare un
numero ben preciso di cifre sia intere che decimali della variabile indicata.
Il primo numero rappresenta l’ampiezza del campo occupato dall’intero numero visualizzato (parte intera
più eventuale parte decimale). Se il valore indicato, è più piccolo di quello effettivamente necessario, il
numero di cifre visualizzate viene esteso al minimo indispensabile, mentre, se è maggiore, vendono
aggiunti degli spazi a sinistra.
Il secondo numero invece indica quante cifre decimali vengono visualizzate.
6 Funzioni aritmetiche standard
Il TURBO-PASCAL mette a disposizione dell’operatore una serie di funzioni aritmetiche predefinite,
utilizzabili direttamente dal programmatore. Alcune di esse saranno adoperate nei prossimi esempi.
Nella tabella 7 è sinteticamente descritta la funzione che ciascuna di esse esplica e il tipo di argomento
con cui opera. In tale tabella sono anche inserite le funzioni di conversione che convertono un tipo di dato
in un altro tipo.
Tab. 7
Tipo
Descrizione
Sin(x)
Cos(x)
ArcTan(x)
Sqr(x)
Sqrt(x)
Esegue il seno dell’argomento tra le parentesi.
Esegue il coseno dell’argomento tra le parentesi.
Esegue l’arcotang. dell’argomento tra le parentesi.
Esegue il quadrato dell’argomento tra le parentesi.
Esegue la radice quadrata dell’argomento tra
parentesi.
Restituisce il valore assoluto dell’argomento tra
parentesi.
Restituisce la parte intera dell’argomento tra
parentesi.
Restituisce la parte frazionaria dell’argomento tra
parentesi.
Esegue il logaritmo naturale dell’argomento tra
parentesi.
Esegue l’esponenziale dell’argomento tra parentesi.
Restituisce il valore 3.14159265.(il tipo restituito è
reale).
Arrotonda il valore x real con uno di tipo
longint.
Tronca il valore x real restituendo un longint.
Restituisce il carattere ASCII corrispondente a x.
Restituisce un valore intero relativo al tipo ordinale x.
Abs(x)
Int(x)
Frac(x)
Ln(x)
Exp(x)
Pi
Round(x)
Trunc(x)
Chr(x)
Ord(x)
Tipo
argomento
reale
reale
reale
intero o reale
reale
intero o reale
reale
reale
reale
reale
reale
reale
intero
intero o reale
7 Le strutture nel TURBO PASCAL
Si prenderanno ora in considerazione quelle istruzioni che permettono l’esecuzione condizionata di parti
del programma.
Le strutture che il Pascal mette a disposizione del programmatore sono illustrate nella tabella 8. Sono
strutture selettive e iterative. Si tenga presente che la struttura di selezione case non rientra tra le
strutture elementari potendo essere sostituita da un insieme di if ..then.
Tab. 8
b) if
condizione
then istruzione1 (o
blocco istruz. 1)
else istruzione2 (o blocco istruz. 2)
c) case espressione... of
etichetta case : istruzione1
etichetta case : istruzione2
Se si verifica la condizione allora
esegui istruzione.
Se si verifica la condizione allora
esegui istruzione1 altrimenti
istruzione2.
Se espressione è uguale ad una delle
etichette case esegui la relativa
istruzione.
.......................................
..
etichetta case : istruzioneN
end;
d) case
espressione... of
etichetta case : istruzione1
etichetta case : istruzione2
Se espressione è uguale ad una delle
etichette case esegui la relativa
istruzione.
a) if
condizione
then istruzione...
.......................................
..
etichetta case : istruzioneN
else
istruzioneM
end;
e) while
condizione
do
istruzione (o
blocco
istruzioni)
f) repeat
istruzione (o blocco istruzioni)
until condizione.
g) for
indice
espressione2
do ...
:=
espressione1
h) for
indice := espressione1
espressione2
do ...
to
downto
Altrimenti esegui istruzioneM.
Mentre è verificata la condizione
esegui istruzione (o blocco
istruzioni).
Ripeti istruzione (o blocco
istruzioni) fino a quando non è vera
la condizione.
Per indice che varia dal valore
espressione1
al
valore
espressione2
esegui
quanto
segue ed incrementa indice di uno.
Per indice che varia dal valore
espressione1
al
valore
espressione2 esegui quanto segue
e decrementa indice di uno.
Le strutture riportate possono essere descritte con diagrammi di flusso che ne permettono una rapido
esame e un facile apprendimento (figure 1 e 2).
7.1 - Strutture condizionali (selettive)
Le strutture di tipo condizionale permettono di effettuare una scelta tra una o più condizioni che si
presentano nello svolgimento del programma, svolgendo una parte di esso piuttosto che un’altra, a
seconda del verificarsi o meno della/delle condizioni poste.
if...then
La sintassi della struttura è:
if
condizione
then istruzione..
if.... then....else
La sintassi della struttura è:
if
condizione
then istruzione1 (o blocco istruz. 1)
else istruzione2 (o blocco istruz. 2)
In tali strutture viene inizialmente controllato che la condizione sia verificata. In caso affermativo viene
eseguita l’istruzione che segue o un blocco di istruzioni (in tal caso racchiuse tra un begin ... end).
Se la condizione risulta invece falsa il programma prosegue senza che venga eseguita l’istruzione (o il
blocco di istruzioni) dopo il then.
case
La sintassi della struttura è la seguente:
case
espressione... of
etichetta case : istruzione1
etichetta case : istruzione2
.............................................
etichetta case : istruzioneN
end;
case.....else
La sintassi della struttura è la seguente:
case
espressione... of
etichetta case : istruzion 1
etichetta case : istruzione2
..........................................
etichetta case : istruzioneN
else
istruzioneM
end;
La struttura case viene utilizzata in sostituzione di istruzioni if ...then multiple, quando deve essere
operata una scelta tra vari casi. Se una delle etichette case risulta uguale al valore che assume
espressione viene eseguita la corrispondente istruzione. Le etichette debbono essere dello stesso tipo
di espressione.
Nel caso che non si verifichi l’eguaglianza per nessuna delle etichette, se è presente l’else, viene
eseguita l’istruzione ad essa riferita, altrimenti il programma prosegue senza che sia stata effettuata
alcuna scelta.
FALSA
CONDIZIONE
FALSA
VERA
CONDIZIONE
ISTRUZIONE
O BLOCCO
ISTRUZIONI
ISTRUZIONE 1
O BLOCCO
ISTRUZIONI
IF .... THEN ....ELSE
IF .... THEN
ESPRES.
=
ETICHETTA 1
?
VERA
ISTRUZIONE 1
ESPRES.
=
ETICHETTA 1
?
VERA
ISTRUZIONE 1
FALSA
FALSA
ESPRES.
=
ETICHETTA 2
?
ISTRUZIONE 2
O BLOCCO
ISTRUZIONI
VERA
ISTRUZIONE 2
ESPRES.
=
ETICHETTA N
?
VERA
ISTRUZIONE N
FALSA
FALSA
ESPRES.
=
ETICHETTA N
?
VERA
ISTRUZIONE N
ISTRUZIONE M
FALSA
CASE ... OF
CASE ... OF ... ELSE
Fig. 1
7.2 Strutture iterative
Le strutture iterative permettono di ripetere l’esecuzione di una determinata parte di programma
controllando che una certa condizione posta si mantenga vera (while...do) o fino a quando essa non
diviene vera (repeat...until), o per un numero assegnato di volte (for...).
while ... do
La sintassi della struttura è:
while
condizione
do
istruzione (o begin blocco istruzioni
end)
repeat ... until
La sintassi della struttura è:
repeat
istruzione (o blocco di istruzioni)
until
condizione
E’ bene evidenziare le differenze fondamentali tra le due strutture:
• while ... do: la condizione viene esaminata all’inizio del ciclo, quindi se essa non è vera prima
di entrarvi, l’istruzione (o blocco di istruzioni) che seguono do non vengono svolte neanche una
volta. Se l’istruzione (o le istruzioni) che seguono do non modificano prima o poi la condizione
rendendola falsa, non si esce mai dal ciclo.
• repeat... until: in questo caso la condizione viene esaminata alla fine del ciclo, e quindi esso
viene eseguito sempre almeno una volta. L’uscita avviene quando la condizione diviene vera
(quindi essa deve essere falsa per eseguire ancora il ciclo). Anche ora l’istruzione (o le istruzioni)
che seguono repeat debbono avere la possibilità di modificare la condizione, rendendola vera,
per uscire dal ciclo.
for ...to ... do
La sintassi della struttura è la seguente:
for
indice := espres.1 to espress.2
do .
for ... downto ... do
La sintassi della struttura è la seguente:
for
indice := espres.1 downto espres.2 do ...
I due cicli for rappresentati differiscono solo per l’azione di incremento o decremento dell’indice.
All’indice viene assegnato un valore iniziale; dopodiché il ciclo viene ripetuto tante volte, fino a quando il
valore dell’indice (incrementato o decrementato automaticamente) non raggiunge il valore finale imposto.
Se debbono essere eseguite più istruzioni queste vanno racchiuse tra begin...end.
ISTRUZIONE
O BLOCCO
ISTRUZIONI
CONDIZIONE
FALSA
VERA
CONDIZIONE
FALSA
ISTRUZIONE
O BLOCCO
ISTRUZIONI
VERA
REPEAT .... UNTIL
WHILE .... DO
INDICE =
ESPRESSIONE 1
INDICE
>
ESPRES. 2
?
INDICE =
ESPRESSIONE 1
VERO
INDICE
<
ESPRES. 2
?
FALSO
FALSO
ISTRUZIONE
O BLOCCO
ISTRUZIONI
ISTRUZIONE
O BLOCCO
ISTRUZIONI
INCREMENTA
INDICE DI 1
DECREMENTA
INDICE DI 1
FOR ... TO
VERO
FOR ... DOWNTO
Fig. 2
8 Programmi d’esempio sulle strutture
All’inizio di ogni programma è posto un commento esplicativo. I messaggi posti all’interno
richiedono sempre esplicitamente quale sia, di volta in volta, la grandezza da introdurre. Ai vari
identificatori delle variabili, per quanto possibile, sono stati assegnati nomi in stretta relazione
con le grandezze da utilizzare. Le maiuscole utilizzate per alcuni identificatori, servono solo per
una maggiore chiarezza di lettura, in quanto nel Pascal, non c’è distinzione tra maiuscole e
minuscole nei nomi assegnati alle variabili (gli identificatori pot o Pot sono identici).
Prog. 8 - Programma con la struttura If…then
(*programma di esempio sull'utilizzazione della struttura condizionale
IF ... THEN - ASSEGNATO IL VALORE DI UN RESISTORE, LA SUA POTENZA,
E LA CORRENTE CHE LO ATTRAVERSA CONTROLLA SE TALE VALORE E' AMMISSIBILE
E, IN CASO CONTRARIO, INDICA QUALE E'LA MASSIMA CORRENTE CHE LO PUO'
PERCORRERE - UTILIZZA LA FORMULA
I=√(P/R) *)
program if_then;
var
res, max_cor , cor ,pot
: real;
begin
writeln;
write ('INTRODURRE IL VALORE DEL RESISTORE
[Ω] '); readln (res);
write ('INTRODURRE IL VALORE DELLA POTENZA
[W] '); readln (pot);
write ('INTORDURRE LA CORRENTE CHE LO ATTRAVERSA [A] '); readln (cor);
max_cor := sqrt (pot/res) ;
if max_cor >= cor then writeln (' CORRENTE REGOLARE ');
if max_cor < cor then
begin
writeln (' CORRENTE NON REGOLARE ');
writeln (' LA MASSIMA CORRENTE AMMISSIBILE E'' ',max_cor:5:3,' A');
end
end.
Osservazioni:
• Notare come il blocco di istruzioni dopo il secondo if...then, è racchiuso tra un begin...end.
• Alla variabile di uscita max_cor, di tipo reale, è stata applicata la formattazione
(:5:3)assegnando l’ampiezza del campo, in altre parole il numero di posti totali che occuperà sul
video, (primo numero dopo i due punti), riservando ad esso 5 posizioni, e poi, dopo i secondi due
punti, il numero di cifre decimali che verranno stampate dopo il punto (nell’esempio 3). In
mancanza di tale indicazione il valore della variabile sarebbe visualizzato in formato
esponenziale.
Prog. 9 - Programma con la struttura if…then…else
(*programma di esempio sull'utilizzazione della struttura condizionale
IF ... THEN ... ELSE - CALCOLA IL VALORE MEDIO DI UNA TENSIONE SINUSOID.
RADDRIZZATA A SEMPLICE O DOPPIA SEMIONDA- UTILIZZA LE FORMULE:
Vmed = Vmax/π
- PER SEMPLICE SEMIONDA Vmed = (2*Vmax)/π - PER DOPPIA SEMIONDA
*)
program if_then_else;
const
pigreco = 3.141592;
var
scelta
: integer;
Vmed,Vmax
: real;
begin
writeln;
writeln (' CALCOLO DEL VALORE MEDIO DI UNA TENSIONE SINUSOIDALE');
writeln (' RADDRIZZATA A SEMPLICE O DOPPIA SEMIONDA');
writeln;
write ('INTRODUCI VALORE MASSIMO ');
readln (Vmax);
write ('INTRODUCI UNO PER SEMIONDA O DUE PER DOPPIA SEMIONDA ');
readln (scelta) ;
if scelta = 1 then
begin
Vmed:=Vmax/pigreco;
writeln ('IL VALORE MEDIO PER SINGOLA SEMIONDA E'' ',Vmed:5:3, ' Volt');
end
else
begin
Vmed:=(2*Vmax)/pigreco;
writeln ('IL VALORE MEDIO PER DOPPIA SEMIONDA E'' ',Vmed:5:3, ' Volt');
end
end.
Prog. 10 - Programma con la struttura case ... of ... else
(*PROGRAMMA DI ESEMPIO SULL'UTILIZZAZIONE DELLA STRUTTURA CONDIZIONALE
CASE ... OF ... ELSE - ASSEGNATO IL VALORE DELLA TENSIONE DI UNO ZENER
E SCEGLIENDO TRA TRE POSSIBILI VALORI DI POTENZA MASSIMA DISSIPABILE
DAL DIODO, CALCOLA IL MASSIMO VALORE DELLA CORRENTE AMMISSIBILE
- UTILIZZA LA FORMULA Pmax=Vz x Izmax *)
program case_of;
var
selettore
: integer;
Vz, Izmax, Pmax
: real;
begin
writeln;
writeln ('CALCOLO DELLA MASSIMA CORRENTE PER UN DIODO ZENER ');
writeln ('SCEGLIERE LA POTENZA MASSIMA DISSIPABILE DALLO ZENER');
writeln ('1- Pmax = 0.5 W
2- Pmax = 1 W
3- Pmax = 1.5 W - ');
readln (selettore);
case selettore of
1 : Pmax:= 0.5 ;
2 : Pmax:= 1
;
3 : Pmax:= 1.5 ;
else
writeln;
writeln ('POTENZA NON CORRETTAMENTE DEFINITA - ASSUNTA = 1 W');
Pmax:= 1 ;
end;
writeln;
writeln ('INTRODUCI IL VALORE DELLA TENSIONE DELLO ZENER '); readln (Vz);
Izmax:=Pmax/Vz;
writeln;
writeln ('LO ZENER HA UNA Pmax = ',Pmax:2:1,' W');
writeln ('MASSIMA CORRENTE AMMISSIBILE PER LO ZENER: ',Izmax:4:3,' A');
end.
Prog. 11 - Programma con la struttura while…do
(*PROGRAMMA DI ESEMPIO SULL'UTILIZZAZIONE DELLA STRUTTURA ITERATIVA
WHILE ... DO - CALCOLA IL VALORE DELLA TENSIONE DI USCITA (Vu) PER
UN PARTITORE DI TENSIONE ASSEGNATI I VALORI DELLA TENSIONE DI
INGRESSO (Vi) E DEI RESISTORI R1 E R2 - IL CALCOLO VIENE ESEGUITO
PER DIVERSI VALORI DI R2 FINO A QUANDO NON SI PONE R2 = 0 E' UTILIZZATA LA FORMULA:
R2
Vu = Vi x —————————
R1 + R2
*)
program while_do;
var
Res1,Res2,Vi,Vu : real;
begin
writeln;
writeln ('CALCOLA IL VALORE DELLA TENSIONE DI USCITA DI UN PARTITORE ');
writeln ('DI TENSIONE - RIPETE IL CALCOLO PER VARI VALORI DI R2 ');
writeln;
writeln ('
PER TERMINARE PORRE R2 = 0 ');
writeln;
write ('INSERIRE IL VALORE DELLA TENSIONE D''INGRESSO [V] ');
readln (Vi);
write ('INSERIRE IL VALORE DI R1
[Ω] ');
readln (Res1);
writeln;
Res2:=1 ;(* PONE R2 DIVERSO DA ZERO IN MODO CHE SIA VERA LA CONDIZIONE
QUANDO SI ENTRA NEL WHILE...DO *)
while res2 <> 0 do
begin
writeln;
writeln ('PER TERMINARE INSERIRE R2=0 ');
write ('SCEGLIERE IL VALORE DELLA RESISTENZA
R2 [Ω] ');
readln (Res2);
Vu:= Vi*(Res2/(Res1+Res2));
writeln ('LA TENSIONE D''USCITA DEL PARTITORE E''
',Vu:5:4,' V');
end;
end.
Nel listato sopra riportato si notino gli aspetti più significativi: prima di entrare nel ciclo while...do si
deve essere sicuri che la condizione sia vera; ciò nel programma è stato fatto assegnando alla variabile
Res2 un valore tale che renda sicuramente vera la condizione. Si esce dal loop (ciclo) quando la
condizione diviene vera (Res2 = 0)
Prog. 12 - Programma con la struttura repeat…until
(*PROGRAMMA DI ESEMPIO SULL'UTILIZZAZIONE DELLA STRUTTURA ITERATIVA
REPEAT...UNTIL - CALCOLA LE CORRENTI I1 E I2 CHE PERCORRONO I RAMI
DI UN PARTITORE DI CORRENTE REALIZZATO CON DUE RESISTORI R1 E R2 POSTI
IN PARALLELO - E' RICHIESTA LA CORRENTE TOTALE It E I VALORI DEI DUE
RESISTORI - IL PROGRAMMA TERMINA QUANDO UNO DEI DUE RESISTORI E'
POSTO UGUALE A ZERO - SONO UTILIZZATE LE FORMULE:
R2
R1
I1 = It x ——————————
I2= It x ————————
R1 + R2
R1 + R2
*)
program repeat_until;
var
Res1,Res2,It ,I1,I2: real;
begin
writeln;
writeln ('CALCOLA LE CORRENTI I1 E I2 CHE PERCORRONO I RAMI DI UN ');
writeln ('PARTITORE DI CORRENTE - R1 E R2 COSTITUISCONO I DUE RAMI');
writeln ('E It LA CORRENTE TOTALE ENTRANTE NEL PARTRITORE - RIPETE');
writeln ('IL CALCOLO PER VARI VALORI DELLE RESISTENZE FINO A QUANDO');
writeln ('UNA DELLE DUE NON ASSUME UN VALORE UGUALE A ZERO -');
writeln;
write ('SCEGLIERE IL VALORE DELLA CORRENTE TOTALE [A] ');
readln (It);
repeat
writeln;
writeln ('PER TERMINARE INSERIRE R1=0 O R2=0');
write ('SCEGLIERE IL VALORE DELLA RESISTENZA R1 [Ω] ');
readln (Res1);
write ('SCEGLIERE IL VALORE DELLA RESISTENZA R2 [Ω] ');
readln (Res2);
if not ((Res1=0) and (Res2=0)) then (*SE R2=0 E R1=0 NON EFFETTUA CALCOLO*)
begin
I1:=It*(Res2/(Res1+Res2));
I2:=It*(Res1/(Res1+Res2));
writeln ('LA CORRENTE CHE PERCORRE R1 E'' ',I1:9:6,' A');
writeln ('LA CORRENTE CHE PERCORRE R2 E'' ',I2:9:6,' A');
end;
until ((Res1 = 0) or (Res2 = 0)) (*SE Res1=0 o Res2=0 ESCE *)
end.
Osservazioni:
• Nell’esempio sopra riportato si osservi come ora non è più necessario assegnare un valore
predeterminato alla variabile prima di entrare nel ciclo. Esso viene eseguito almeno una volta. Si
esce ora dal loop quando la condizione è vera; deve essere uguale a zero una delle resistenze o
ambedue. In tal caso, per evitare che si verifichi un errore di divisione per zero, con un if il
calcolo non viene fatto eseguire. Infatti solo se non (not) è R1 = 0 e contemporaneamente
(and) R2 = 0 vengono calcolate le correnti.
• A differenza del while...do, se ora tra repeat e until è posto un blocco di istruzioni, invece
di una sola, non è necessario inserire il begin...end che le racchiuda.
Prog. 13 - Programma con la struttura for…to…do
(*PROGRAMMA DI ESEMPIO SULL'UTILIZZAZIONE DELLA STRUTTURA ITERATIVA
FOR ... TO - CALCOLA 10 VALORI DELLA TENSIONE DI USCITA (Vu) PER UN
PARTITORE DI TENSIONE CON CARICO ALL'USCITA. SONO ASSEGNATI I VALORI
DELLA TENSIONE D'INGRESSO (Vi), DEI RESISSTORI DEL PARTITORE R1 E R2
E DEL RESISTORE DI CARICO Rc - Rc VIENE DIMINUITO OGNI VOLTA DI UN
DECIMO DEL VALORE INIZIALE - UTILIZZA LA FORMULA:
Rp
Vu= Vi* ———————
CON
Rp = R2//Rc
R1+Rp
*)
program for_to;
const
pigreco = 3.141592
var
i :integer;
Res1,Res2,Rescar,Respar,Rescar_ini,Vu,Vi : real;
begin
writeln;
writeln ('CALCOLO DI 10 VALORI DELLA TENSIONE DI USCITA DI UN PARTITORE');
writeln ('DI TENSIONE CON CARICO - SONO ASSEGNATI I VALORI DELLA TENSIONE');
writeln ('DI INGRESSO, DEI RESISTORI R1 E R2 DEL PARTITORE E DI QUELLO DI');
writeln ('CARICO Rc - Rc VIENE DIMINUITO OGNI VOLTA DI UN DECIMO DEL SUO');
writeln ('VALORE INIZIALE');
writeln;
write ('SCEGLIERE IL VALORE DELLA TENSIONE D''INGRESSO [V] ');
readln (VI);
write ('SCEGLIERE IL VALORE DELLA RESISTENZA R1
[Ω] ');
readln (Res1);
write ('SCEGLIERE IL VALORE DELLA RESISTENZA R2
[Ω] ');
readln (Res2);
write ('SCEGLIERE IL VALORE DELLA RESISTENZA Rc
[Ω] ');
readln (Rescar);
writeln;
Rescar_ini:=Rescar;
for i:=1 to 10 do
begin
Respar:=(Res2*Rescar)/(Res2+Rescar); (*CALCOLA PARALLELO CARICO E R2*)
Vu:=Vi*(Respar/(Res1+Respar));
(*CALCOLA TENSIONE D'USCITA*)
write('RESISTENZA DI CARICO = ',Rescar:12:3, ' Ω ');
writeln ('
TENSIONE D''USCITA = ',Vu:5:3, ' V');
Rescar:=Rescar-Rescar_ini/10 ;
end; (*fine del loop for...do*)
end.
9 Funzioni e procedure
Durante la stesura di un programma, capita spesso di dover utilizzare blocchi di istruzioni ripetitivi, che
esplicano cioè la stessa funzione, posti in punti diversi del programma stesso. In questo caso, conviene
utilizzare il blocco di istruzioni, come una parte del programma a se stante, che può essere chiamata
ogni volta che si vuole utilizzare, da ciascun punto, il blocco stesso. Viene creato così, quello che viene
detto sottoprogramma (o subroutine).
Nel Pascal esistono due tipi diversi di sottoprogramma, che anche se molto simili, hanno struttura e
compiti diversi. Questi sono le funzioni e le procedure.
Una funzione in TURBO-PASCAL è un sottoprogramma che restituisce, una volta che ha esplicato il
proprio compito, un solo valore al programma chiamante.
Quando invece il sottoprogramma svolge compiti diversi, senza però che debba restituire uno specifico
valore al programma chiamante, si parla di procedura. Normalmente quando si chiama una funzione o
una procedura bisogna passare ad esse dei dati su cui operare, per ottenere i risultati voluti. Questi dati,
ad esse forniti, sono detti parametri.
Esiste tuttavia la possibilità di utilizzare sia le funzioni che le procedure senza operare un effettivo
passaggio dei parametri. Anche se tale metodo semplifica la loro utilizzazione, non sempre è
raccomandabile in quanto può produrre effetti non desiderati e difficilmente controllabili.
Come è stato visto nella descrizione della struttura generale di un programma (→ Programma 5), le
procedure e le funzioni debbono essere poste prima del corpo del programma principale. Se sono
precedute da dichiarazioni di variabili sono dette variabili globali in quanto possono essere adoperate e
modificate, oltre che dal programma principale, da tutte le funzioni e procedure che le seguono [5]. In tal
modo, se si fanno lavorare direttamente procedure e funzioni con le variabili globali, può essere omesso
il passaggio di parametri.
Ogni procedura o funzione deve poi essere strutturata all’interno nella stessa maniera di un generico
programma, contenendo la dichiarazione di costanti, variabili, definizione di dati, eventuali procedure e
funzioni interne e il corpo principale. Le variabili dichiarate all’interno della procedura o funzione sono
dette variabili locali, in quanto non possono essere utilizzate al loro esterno.
Sono riportati di seguito gli esempi di strutture di una funzione e di una procedura.
________________________
[5]
Nel Pascal standard la struttura di un programma deve essere necessariamente quella illustrata nel paragrafo 4. Nel TURBOPASCAL invece, possono esserci dichiarazioni di variabili e costanti e definizioni di tipi anche dopo le procedure e le funzioni. In tal
caso
però
esse
non
possono
essere
utilizzate
dalle
procedure
e
funzioni
che
le
precedono.
____________________________
Struttura di una funzione:
function nome_della_funz. (lista parametri): tipo funz.;
const dichiarazione delle costanti locali;
type definizione dei tipi di dati locali;
var
dichiarazione delle variabili locali;
begin
istruzioni della funzione;
end
Struttura di una procedura:
procedure nome_della _procedura (lista parametri);
const
dichiarazione delle costanti locali;
type
definizione dei tipi di dati locali;
var dichiarazione delle variabili locali;
begin
istruzioni della procedura;
end.
All’interno delle funzioni e delle procedure possono esistere altre procedure e altre funzioni.
Come si vede dalle strutture sopra riportate, le funzioni e le procedure hanno una forma simile. È da
evidenziare che nella dichiarazione della funzione, all’elenco dei parametri deve seguire anche l’esplicita
indicazione del tipo di dato che essa deve restituire (esso è posto, nella dichiarazione, dopo i due punti
ed è indicato con tipo_funzione).
10 Programmi d’esempio su funzioni e procedure
Esempio di funzione con uso di variabili globali senza passaggio di parametri. In tale esempio alla
funzione non saranno passati parametri, ma essa utilizzerà per effettuare le elaborazioni, le variabili
globali dichiarate all’inizio del programma. Tutte le eventuali operazioni che essa compirà sulle variabili,
le modificheranno.
Prog. 14 - Programma con funzione senza passaggio dei parametri
(*CALCOLA LA TENSIONE ALL'USCITA DI UN PARTITORE ASSEGNATA LA TENSIONE
D'INGRESSO, E LE DUE RESISTENZE- ESEGUE IL CALCOLO PER 3 VALORI DIVERSI
DELLA RESISTENZA R2 - USA UNA FUNZIONE CON VARIABILI GLOBALI SENZA
PASSAGGIO DI PARAMETRI Vi
E' UTILIZZATA LA FORMULA :
Vr1=————————— x R1
R1 + R2
*)
program uso_fun1;
var
R1, R2, Vi, Vr1, K
(*VARIABILI GLOBALI *)
:real;
function partitore
:real; (*FUNZIONE SENZA PARAMETRI DI TIPO REALE*)
begin
R2:=K*R1;
partitore := Vi* R1 / (R1 + R2) ; (*CALCOLA TENSIONE D'USCITA*)
end;
begin ;
(*INIZIO PROGRAMMA PRINCIPALE*)
writeln;
writeln ('CALCOLO DELLA TENSIONE ALL''USCITA DI UN PARTITORE RESISTIVO');
writeln;
write ('INTRODUCI TENSIONE D''INGRESSO [V] '); readln (Vi);
write ('INTRODUCI RESISTENZA R1
[Ω] ') ; readln (R1);
writeln;
K := 1/2;
Vr1 := partitore
; (*CHIAMA LA FUNZIONE*)
writeln ('R2= ',R2:10:2,'[ê]
Vr1= ',Vr1:6:3,' [V]');
K
:= 1;
Vr1 := partitore
; (*CHIAMA LA FUNZIONE*)
writeln ('R2= ',R2:10:2,'[ê]
Vr1= ',Vr1:6:3,' [V]');
K
:= 2;
Vr1 := partitore
; (*CHIAMA LA FUNZIONE*)
writeln ('R2= ',R2:10:2,'[ê]
Vr1= ',Vr1:6:3,' [V]');
end.
;(*FINE PROGRAMMA PRINCIPALE*)
Osservazioni:
• La funzione chiamata restituisce un valore che viene assegnato alla variabile Vr1. Il programma
principale assegna un valore al parametro K che, essendo una variabile globale, è utilizzato, con
il valore attribuitogli, anche dalla funzione. A sua volta la funzione assegna un valore all’altra
variabile globale R2. Il valore ad essa attribuito viene visualizzato poi nel corpo del programma
principale.
• Come si vede quindi, le variabili modificate in una qualsiasi parte del programma, sono disponibili,
così come modificate, globalmente, sia all’interno del programma principale, che nel corpo delle
funzioni stesse.
• Si deve osservare che, tale proprietà, in programmi di una certa complessità, rende possibile
realizzare errori difficilmente individuabili, dovuti a un’accidentale modifica di qualche variabile
globale.
Nel Pascal esistono due diversi modi di passare i parametri alle funzioni e alle procedure: il passaggio
per valore o il passaggio per indirizzo.
Nel passaggio per valore, eventuali modifiche operate dalla funzione sul parametro non alterano il
valore che esso aveva prima della chiamata. Quindi le manipolazioni del parametro all’interno della
funzione o della procedura, rimangono al loro interno, non producendo alcun cambiamento nel
programma chiamante.
Prog. 15 - Programma con passaggio dei parametri per valore
(*CALCOLA LA TENSIONE ALL'USCITA DI UN PARTITORE ASSEGNATA LA TENSIONE
D'INGRESSO, E LE DUE RESISTENZE- ESEGUE IL CALCOLO PER 3 VALORI DIVERSI
DELLA RESISTENZA R2 - USA UNA FUNZIONE CON PASSAGGIO DEI PARAMETRI PER
VALORE (NON MODIFICABILI DALLA FUNZIONE CHIAMATA)Vi
E' UTILIZZATA LA FORMULA :
Vr1= ——————— x R1
R1 + R2
*)
program uso_fun1;
var
R1, R2, Vi, Vr1
:real;
(*VARIABILI GLOBALI*)
function partitore(R1,R2,Vi:real):real; (*FUNZIONE CON PARAMETRI*)
begin
partitore := Vi * R1 / (R1 + R2) ; (*CALCOLA TENSIONE D'USCITA*)
R1:=0 ; Vi:=0 ;
end;
(*QUESTA VARIAZIONE DEI PARAMETRI NON INFLUENZA LE VARIABILI GLOBALI*)
begin ;
(*INIZIO PROGRAMMA PRINCIPALE*)
writeln;
writeln ('CALCOLO TENSIONE ALL''USCITA DI UN PARTITORE RESISTIVO');
writeln;
write ('INTRODURRE TENSIONE D''INGRESSO [V] '); readln (Vi);
write ('INTRODURRE RESISTENZA R1
[Ω] ') ; readln (R1);
writeln;
R2 := R1/2;
Vr1 := partitore(R1,R2,Vi)
;
(*CHIAMA LA FUNZIONE*)
writeln ('R2= ',R2:10:2,'[Ω]
Vr1= ',Vr1:6:3,' [V]');
R2 := R1;
Vr1 := partitore(R1,R2,Vi)
;
(*CHIAMA LA FUNZIONE*)
writeln ('R2= ',R2:10:2,'[Ω]
Vr1= ',Vr1:6:3,' [V]');
R2 := 2*R1;
Vr1 := partitore(R1,R2,Vi)
;
(*CHIAMA LA FUNZIONE*)
writeln ('R2= ',R2:10:2,'[Ω]
Vr1= ',Vr1:6:3,' [V]');
end.
;
(*FINE PROGRAMMA PRINCIPALE*)
Osservazioni:
• In questo secondo esempio il programma chiamante passa alla funzione un certo numero di
parametri; essi debbono essere nello stesso ordine e dello stesso tipo, sia nella dichiarazione
della funzione sia nella chiamata. Gli identificatori utilizzati per i parametri possono essere uguali
o differenti da quelli utilizzati nel corpo della funzione. Nell’esempio riportato sono stati usati gli
stessi nomi per i parametri sia nella chiamata sia nella descrizione della funzione (R1,R2 e Vi).
• Per evidenziare come una modifica effettuata nel corpo della funzione su un parametro passato
per valore non lo cambi nel programma principale, è stato posto all’interno della funzione R2
uguale a zero. Il programma principale, al termine della chiamata, quindi visualizza per R2 il
valore che esso aveva prima della esecuzione della funzione e non quello modificato.
Nel passaggio per indirizzo se la funzione o procedura effettueranno modifiche sui parametri, esse si
ripercuoteranno anche sui valori che essi avevano prima della chiamata.
Quando il programmatore desidera effettuare il passaggio di parametri per indirizzo, la lista dei parametri
posta entro le parentesi tonde dopo il nome, deve essere fatta precedere dalla parola chiave Var .
Prog. 16 – Programma con procedura con passaggio dei parametri per indirizzo e per valore
(*CARICA DI UN CONDENSATORE CON TENSIONE A GRADINO ALL'INGRESSO E CON
RESISTORE IN SERIE - VENGONO CALCOLATI 20 VALORI DELLA TENSIONE Vc
ASSEGNANDO L'AMPIEZZA DEL GRADINO, IL VALORE DELLA RESISTENZA E DELLA
CAPACITA' E L'INTERVALLO DI TEMPO PER OGNI MISURA - SI FA USO DI UNA
PROCEDURA CON PASSAGGIO DI PARAMETRI FORMULA UTILIZZATA
-(t/τ)
Vc=Vm x (1-e
)
CON τ=RxC
*)
program uso_proc;
var
Vc,Vm,R,C,dt,t,tf,tau,diff
:real; (*VARIABILI GLOBALI*)
procedure tensione(Res,Con,t,dt,tau:real; var Vcond,tfin :real);
var
(*VARIABILI LOCALI DELLA PROCEDURA*)
i :integer;
begin
for i:=1 to 20 do
begin
Vcond:=Vm*(1- exp(-t/tau));
t:=t+dt;
writeln ('t= ',t:12:8, ' [s] Vc= ',Vcond:8:3,' [V]');
end;
(*FINE FOR*)
tfin:=t;
end;
(*FINE PROCEDURA*)
begin
(*INIZIO PROGRAMMA PRINCIPALE*)
writeln;
writeln ('CALCOLO DELLA CARICA DI UN CONDENSATORE IN UN CIRCUITO R-C');
writeln ('VENGONO ASSEGNATI IL VALORE DELLA CAPACITA'', DELLA RESISTENZA');
writeln ('E DELLA TENSIONE DI ECCITAZIONE A GRADINO - SONO CALCOLATI');
writeln ('20 VALORI AD INTERVALLI REGOLARI DI TEMPO CON INIZIO DA t=0 ');
writeln ('secondi - ');
write ('INTRODURRE VALORE DELLA CAPACITA''
[µF] '); readln (C);
write ('INTRODURRE VALORE DELLA RESISTENZA [Ω] ')
; readln (R);
write ('INTRODURRE AMPIEZZA DEL GRADINO
[V] ')
; readln (Vm);
tau:=R*C*1E-6 ;
(*CALCOLO COSTANTE DI TEMPO*)
dt:=(6*tau)/20;
(*CONDENSATORE CARICO DOPO 6 VOLTE COSTANTE TEMPO*)
Vc:=0; t:=0; tf:=0;
tensione(R,C,t,dt,tau,Vc,tf);
diff:=Vm-Vc;
writeln ('PER COMPLETARE LA CARICA DEL CONDEN. AL TEMPO ',tf:12:8,' sec.');
writeln ('MANCANO ',diff:8:3,' V');
end.
Osservazioni:
• Nel Programma 16 viene usata una procedura a cui vengono passati parametri sia per valore
(Res, Con, t, dt, tau) che per indirizzo (Vcond, tfin). Questa volta per i parametri
sono stati utilizzati nomi diversi rispetto alle variabili utilizzate nel programma principale. La
variazione prodotta dalla procedura su Vcond, che coincide con Vc, è utilizzata poi alla fine del
programma principale, così come è usato il valore di tfin che corrisponde a tf.
• Per stabilire il tempo finale, viene utilizzata la relazione di carattere pratico tfin ≅ (5 ÷6)[6]. Per
questo l’incremento Dt viene assunto come tfin : 20.
• Al termine del programma viene visualizzato il tempo finale ed il valore di tensione che manca per
completare
la
carica.
____________________
[6]
Secondo tale relazione, la carica del condensatore può ritenersi molto vicino al valore finale, dopo circa 5 o 6 volte il
valore della costante di tempo (in teoria il condensatore tende asintoticamente al valore massimo della carica,
raggiungendola
solo
per
t
=
∞
).
_______________________
11 Tipi di dati strutturati
I dati finora utilizzati (char, integer, real, boolean) sono tutti definiti tipi semplici. Nel Pascal è
tuttavia possibile utilizzare dati di tipo più complesso detti dati strutturati.
Come precedentemente accennato (→ paragrafo 2), i dati strutturati possono essere suddivisi in:
• tipo Array: costituito da un insieme di dati tutti dello stesso tipo;
• tipo Record: costituito da un certo numero di campi che possono essere anche di tipo diverso;
• tipo Set: formato da tutti i possibili sottoinsiemi di un tipo base ordinale (→ paragrafo 2). Il tipo
base non può avere più di 256 elementi (con estremi 0 e 255);
• tipo File: realizzato da una serie lineare di elementi tutti dello stesso tipo (sia semplici che
strutturati), a cui si può accedere solo in modo sequenziale (per accedere ad un elemento
intermedio bisogna scandire prima tutti gli elementi che lo precedono).
Tipo array
Gli array vengono utilizzati quando è necessario memorizzare un certo numero di dati, appartenengono
tutti allo stesso tipo e danno la possibilità di non ricorrere all’uso di un elevato numero di identificatori.
Si utilizza a tale scopo un unico identificatore che individua tutti gli elementi da memorizzare. Per poter
poi contraddistinguere un elemento dall’altro vengono adoperati, in unione con l’identificatore, uno o più
indici. Gli array con un solo indice sono definiti monodimensionali o vettori.
Se per esempio si volessero memorizzare un certo numero di valori di tensione che sono presenti ai capi
di un condensatore in tempi successivi, potremmo utilizzare un array monodimensionale. Se
l’identificatore unico, delle varie tensioni, venisse chiamato Vc, per distinguere un valore dall’altro potrà
essere impiegato un indice, per esempio ind, che variando da 0 ad un determinato valore n, permetterà
di identificare le varie tensioni. Se quindi l’identificatore del vettore è Vc[ind] (l’indice viene posto tra
parentesi quadre), i vari valori di tensione saranno:
Vc[0], Vc[1], Vc[2], Vc[3], .... ,Vc[n]
La dichiarazione degli array viene effettuata in Pascal nel seguente modo [7]:
var
nome_array: array [tipo _indice] of tipo_elementi
dove con nome_array si è indicato l’identificatore dell’array, con tipo_indice, del tipo ordinale, il
numero di elementi che costituiscono l’array e con tipo_elementi, il tipo di dati che formeranno l’array.
Il tipo_indice è costituito normalmente da due elementi del tipo ordinale, separati da due punti. Per gli
array a più dimensioni sono presenti, separati da una virgola, tanti tipi indice quante sono le dimensioni.
______________________
[7]
Gli array possono essere anche dichiarati come tipi; in tal caso bisogna, per referenziarli, dichiarare anche una variabile di tipo
array:
type
nome_array = array [tipo_indice] of tipo_elementi;
var
var_array : nome_array;
_______________________
Esempi di dichiarazioni di array:
var
tensione: array
[1..20]
of real;
dichiara un array, con nome tensione, ad una dimensione, con venti elementi di tipo reale;
var
num: array
[1.. 4, 1..3] of integer;
dichiara un array, a due dimensioni, di interi.
Tale array potrebbe essere rappresentato con la struttura sotto riportata:
Tab. 9
123
-10
67
32
45
5
-9
56
32
12
234
128
Nel programma, dopo la dichiarazione, gli elementi dell’array sono accessibili con un identificatore del
tipo num[r,c], avendo indicato con r il numero di riga e con c il numero di colonna a cui appartiene
l’elemento.
E’ bene precisare che dopo la dichiarazione, i vari elementi non contengono alcun valore significativo;
essi pertanto debbono essere inizializzati.
La tabella 10 evidenzia la relazione tra gli elementi dell’array e i rispettivi identificatori:
Tab. 10
num[1,1]
=
123
num[2,1] = 10
num[3,1]
=
67
num[4,1]
=
32
num[1,2]
45
num[2,2]
5
num[2,2]
-9
num[2,2]
56
=
=
=
=
num[1,3]
32
num[2,3]
12
num[2,3]
234
num[2,3]
128
=
=
=
=
In tale struttura (matrice) con il primo indice sono state indicate le righe (1..4) e con il secondo le colonne
(1..3).
Tipo Record
Il record è una struttura suddivisa in campi. I campi contengono gli elementi che compongono il record.
Tali elementi possono essere di tipo diverso (tipo char, boolean, string, integer, real o
anche di tipo strutturato).
La dichiarazione di un record è effettuata nel modo seguente:
type
var
nome_record = record
nome_campo_1: tipo;
nome_campo_2: tipo;
...............................;
nome_campo_n: tipo;
end;
var_record : nome_record;
La variabile di tipo record var_record serve poi per accedere ai vari campi del record con la seguente
sintassi:
var_record.nome_campo
separando il nome della variabile di tipo record da quello del campo interessato con un punto.
Esempio di dichiarazione di un record contenente dati di tipo diverso:
type
articoli_riviste = record
titolo: string[30];
rivista: string[15];
pagina: byte;
............numero: byte;
anno: integer;
end;
var
articoli : articoli_riviste;
Per esempio per inizializzare il campo titolo nel precedente record si deve scrivere:
articoli.titolo := ‘ELETTRONICA OGGI’
Tipo set
Un dato strutturato di tipo set è formato da tutti i possibili sottoinsieme di un tipo base ordinale (→
paragrafo 2). Non potendo avere il tipo base più di 256 elementi (con estremi 0 e 255), sono ammissibili
come tipo base gli ordinali di tipo byte, char, boolean (ma non integer, word, longint e
shortint che superano il numero di elementi ammissibile o i valori estremi). O anche tipi di dato
ordinali realizzati dal programmatore e precedentemente dichiarati come tipo.
La dichiarazione di un tipo set è fatta nel modo seguente:
type
var
nome_set = set of tipo;
var_set : nome_set;
Esempio di dichiarazione di alcuni set:
type
colore_led = (rosso, verde, giallo);
tipo_colore = set of colore_led;
tipo_byte = set of byte;
tipo_carattere = set of char;
tipo_boolean = set of boolean;
Tipo file
Un file è un insieme di dati dello stesso tipo (sia semplici che strutturati), che possono essere registrati su
una memoria di massa (disco fisso, dischetto o altro dispositivo).
Il file viene detto sequenziale quando la scrittura e la lettura dei dati avviene registrando o leggendo un
dato dopo l'altro, in stretta successione. Per accedere ad un'informazione intermedia bisogna prima
accedere a quelle che la precedono.
Nel TURBO-PASCAL prima di utilizzare un file, bisogna dichiararlo come tipo di dato:
Type
nome_file = file of tipo;
Così per esempio possono essere dichiarati alcuni file:
Type
Var
nomi = file of string[20]
dato = file of real;
elenco: nomi;
numeri: dato;
[8]
;
In tali esempi le variabili di tipo file dichiarate elenco e numeri costituiranno poi il nome logico del file
(cioè il nome con cui si lavorerà senza prendere in considerazione il vero nome con cui il file sarà
registrato sul disco).
_______________
[8]
Nelle versioni del TURBO-PASCAL successive alla 3, volendo memorizzare nei file delle stringhe, deve essere omessa
l’indicazione della lunghezza della stringa; in tal caso dovrebbe porsi:
nomi = file of string.
_______________
12 Procedure e funzioni per la gestione dei file
Nella tabella seguente si presuppone di lavorare con un file a cui è stato assegnato il nome logico
elenco e che esso verrà registrato sul disco A: con il nome nomi.txt.
Tab. 11
ASSIGN(elenco,'A:nomi.txt')
REWRITE(elenco)
RESET(elenco)
APPEND(elenco)
CLOSE(elenco)
WRITE(elenco,cognome)
READ(elenco,città)
EOF(elenco)
FILESIZE(elenco)
SEEK(elenco,numero)
SEEK(elenco,FILESIZE(elenco))
Assegna al nome fisico del file con cui verrà registrato sul
disco ('A: nomi.txt'), il nome logico elenco.
Crea e apre il file elenco registrandolo sul disco A: con il
nome ‘nomi.txt'. Se il file già esiste, il vecchio contenuto
viene perso.
Apre il file elenco per la lettura. Il puntatore del file punterà
al primo dato registrato nel file.
Apre il file elenco (già precedentemente creato) per
aggiungervi nuovi dati.
Chiude il file precedentemente aperto in lettura o in scrittura.
In caso di scrittura, svuota anche il buffer registrando i dati in
esso eventualmente presenti e non ancora scritti su disco.
Scrive la variabile cognome nel file elenco. Il puntatore del
file incrementa automaticamente di una posizione.
Legge un dato dal file elenco e lo assegna alla variabile città.
Il puntatore automaticamente incrementa di una posizione.
Controlla che non si sia raggiunta la fine del file.
Restituisce il numero di dati presenti nel file.
Posiziona il puntatore sul dato del file elenco la cui
posizione è espressa da "numero".
Posiziona il puntatore alla fine del file elenco. Questa
funzione serve per aggiungere in coda nuovi dati ad un file
già esistente. Il file deve essere aperto, in tal caso, con la
funzione RESET.
Dei semplici esempi illustreranno come possano essere utilizzate alcune delle funzioni e procedure per la
gestione dei file.
Prog. 17 - Programma con scrittura e lettura di un file
program prova_file;
type nome = file of string;
var
elenco:nome ;
nome1,nome2: string;
begin
writeln('introduci il tuo nome ');
readln(nome1);
assign(elenco,'A:mio.txt');
rewrite (elenco);
write (elenco,nome1);
close (elenco);
reset (elenco);
read(elenco,nome2);
close (elenco);
writeln('il nome memorizzato su disco è: ',nome2);
end.
Osservazioni:
Per evidenziare che il programma funziona in modo corretto, la stringa salvata su disco, una volta riletta,
viene assegnata alla variabile nome2 invece che nome1.
Il file è stato preparato per lavorare con versioni del TURBO-PASCAL successive alla 3. Per tale motivo
nella dichiarazione delle stringhe non è posta la dimensione tra parentesi quadre. Purtroppo in tale modo
ogni stringa salvata, anche se più corta, occupa 256 byte. Tale inconveniente può essere superato
inserendola stringa in un record e poi salvando il record stesso. Il Programma 18 illustra tale metodo.
Senza fare ricorso ad un record è possibile anche dichiarare prima un tipo stringa di lunghezza
predefinita e poi utilizzare tale tipo per la dichiarazione del file e delle altre variabili stringa adoperate per
le operazioni su file.
Prog. 18 - Programma con scrittura e lettura di un file con uso di record
program prova_file1;
type
nomerec =record
nome1:string[10];
end;
nomefile = file of nomerec;
var
nome2 :string[10];
var_nomerec :nomerec;
var_nomefile :nomefile;
begin
writeln('introduci il tuo nome ');
readln(var_nomerec.nome1);
assign(var_nomefile,'A:mio1.txt');
rewrite (var_nomefile);
write (var_nomefile,var_nomerec);
close (var_nomefile);
reset (var_nomefile);
var_nomerec.nome1:=' ';
read(var_nomefile,var_nomerec);
close (var_nomefile);
writeln('il nome memorizzato su disco è: ',var_nomerec.nome1);
end.
Osservazioni:
L’accesso al campo del record contenente la stringa è ottenuto utilizzando il nome assegnato al campo
(nome1) separato da un punto dalla variabile che referenzia il nome del record (var_nomerec).
13 Procedure e funzioni per il trattamento di stringhe
Bisogna osservare che i dati di tipo string utilizzati fino ad ora non sono a disposizione nel Pascal
Standard. In esso le stringhe vengono trattate come array di caratteri. E’ pertanto lecito considerare tali
tipi di dati, presenti nel TURBO PASCAL, come dati strutturati. [9]
IL TURBO PASCAL prevede una serie di procedure e funzioni che operano sui dati tipo stringa. Nella
tabella 12 viene fornito un elenco di tali procedure e funzioni con una breve descrizione, mentre nella
tabella 13 è illustrata la loro sintassi.
__________________
[9]
I manuali della BORLAND classificano i dati di tipo string come un tipo di dato a sé stante. Tale classificazione è quella
seguita
nel
paragrafo
2
______________________
Tab. 12
Funzione
Length
Concat
Copy
Pos
Procedura
Str
Val
Delete
Insert
Tab. 13
Descrizione
Restituisce la lunghezza di una stringa.
Unisce due o più stringhe.
Restituisce una stringa (sottostringa) che è una parte di
un’altra stringa.
Effettua la ricerca di una stringa (sottostringa) all’interno di
un’altra stringa.
Descrizione
Converte un intero o un reale in una stringa.
Converte una stringa (se di tipo numerico) in un numero di
tipo intero o reale.
Cancella un sottostringa da una stringa.
Inserisce una sottostringa in una stringa.
Funzione
Length(stri)
Concat(stri1,
...)
stri2,
Copy(stri, i, num)
Pos(sottostri, stri)
Procedura
Str(num, stri)
Str(num:larg:dec,stri)
Val(stri, num, cod)
Delete(stri, i, num)
Insert(stri1, stri2, i)
Descrizione
stri: string. Ritorna un risultato di tipo intero che
rappresenta la lunghezza della stringa stri.
stri1,stri2,...:string.
Unisce
le
stringhe
str1,str2,.... Non possono essere superati i 255 caratteri.
La stessa funzione di Concat è ottenuta con l’operatore “
+“
(Esempio: stri1+stri2+...).
stri: string; i ,num: integer. Restituisce una
sottostringa formata da num caratteri prelevati da stri a
partire dall’i-esimo carattere
sottostri,stri:
string. Se la sottostringa
sottostri non viene trovata all’interno della stringa
stri, restituisce zero, altrimenti un numero che indica la
posizione del primo carattere della sottostringa
all’interno della stringa.
Descrizione
num: integer o real; stri: string. Il dato num,
di tipo intero o reale, viene convertito nella stringa stri.
num: integer o real; stri: string; larg,
dec: integer. In questa forma è possibile fissare anche
la larghezza della stringa (larg) e il numero di decimali
(dec).
stri: string; num: integer o real; cod:
integer. La stringa stri, se contiene informazioni
numeriche adatte, viene convertita nel numero num. La
procedura ritorna in cod il valore zero se la conversione
ha operato correttamente.
stri: string; i ,num: integer. Cancella dalla
stringa stri, num caratteri a partrire dal carattere i-esimo.
stri1,stri2,...:string; i: integer. La stringa
stri2, viene inserita in stri1, a partire dalla posizione i.
Se stri1, dopo l’inserimento, supera i 255 caratteri, essa
verrà troncata.
Alcune delle procedure e funzioni sopra riportate verranno utilizzate nei programmi che illustrano le
funzioni grafiche del TURBO PASCAL.
14 I moduli del TURBO-PASCAL
Nelle più recenti versioni del TURBO-PASCAL, alcuni tipi di funzioni e procedure, non presenti nel Pascal
Standard, sono state incluse, in particolari programmi detti moduli.
Il TURBO-PASCAL, mette a disposizione dell’utente un certo numero di moduli standard, ciascuno con
un nome diverso. Ogni modulo riunisce funzioni, procedure, variabili, costanti e tipi di dati raggruppati
omogeneamente.
Quando occorre utilizzare le funzioni o le procedure incluse in un modulo, esso deve essere compilato
unitamente al programma dell’utente.
Alcuni dei moduli standard presenti nel TURBO-PASCAL sono:
• Graph- contenente, come si è detto, le funzioni grafiche.
• Crt- contiene funzioni avanzate per la gestione del testo (finestre di testo).
• Dos- dove sono implementate alcune funzioni particolari del DOS• Printer- modulo per la gestione della stampante.
• System - tale modulo contiene tutte le funzioni e procedure del Pascal non standard implementate
nel TURBO-PASCAL. Tale modulo, anche se non esplicitamente richiesto dall’operatore, viene
sempre unito al programma dell’utente, in fase di compilazione.
Il programmatore per unire al proprio programma uno o più moduli, deve inserire all’inizio del listato,
subito dopo il nome del programma, la parola riservata uses seguita dalla lista dei nomi dei moduli,
separati da una virgola.
Esempio per utilizzare funzioni grafiche e di testo avanzate:
program mio_programma;
uses
Graph, Crt;
const
......
var
.....
I moduli standard (tranne Graph), sono contenuti nel programma TURBO.TPL che deve essere
presente, nel caso si utilizzi uno dei moduli standard, nella stessa direttrice dove si trova il compilatore. Il
programma relativo al modulo Graph, chiamato GRAPH.TPU, deve essere anch’esso presente nella
direttrice del compilatore.
Si tenga presente poi, che esiste anche la possibilità per il programmatore, di realizzare propri moduli.
14.1 - Il modulo Crt
Il video, in modalità testo, è visto come un insieme di righe ciascuna formata da un determinato numero
di caratteri. Il numero di righe e il numero di caratteri per ciascuna di esse, è legato alla particolare
modalità video presente nel computer. Ecco alcune delle modalità che il TURBO-PASCAL è in grado di
gestire:
Tab. 14
Descrizione
40 caratteri x 25 righe monocromatiche
40 caratteri x 25 righe a colori
80 caratteri x 25 righe monocromatiche
80 caratteri x 25 righe a colori
80 caratteri x 43 righe (con adattatore
EGA)
80 caratteri x 50 righe (con adattatore
VGA)
______________________
modalità
denominata
modalità
denominata
modalità
denominata
modalità
denominata
modalità EGA
modalità VGA
Modo
BW40 = 0
C40 = 1 [10]
BW80 = 2
C80 = 3
Font 8 x 8 = 256
Font 8 x 8 = 256
L’angolo in alto a sinistra corrisponde alle coordinate 1,1 (prima riga, prima colonna).
Nel modulo Crt sono presenti particolari funzioni e procedure di gestione del video in modo testo non
incluse nel Pascal Standard.
E’ possibile, tra l’altro, con la sua utilizzazione, suddividere il video in diverse zone rettangolari, dette
finestre (windows), su cui operare in modo indipendente dalle altre. Una sola window per volta può
essere quella attiva.
Funzioni e procedure del modulo Crt
Tab. 15
Tabella descrizione funzioni e procedure modulo Crt
TextMode
Attiva il modo di testo selezionato.
ClrScr
Cancella il video e pone il cursore nell’angolo in alto a sinistra
(1,1).
ClrEol
Cancella tutti i caratteri di una riga dalla posizione del cursore
alla sua fine.
DelLine
Cancella la riga su cui è posizionato il cursore.
InsLine
Inserisce una linea vuota sotto quella su cui è posizionato il
cursore.
GotoXY
Sposta il cursore sulla riga X e colonna Y indicate.
WhereX
Ritorna la posizione della riga su cui si trova il cursore
WhereY
Ritorna la posizione della colonna su cui si trova il cursore
TextBackground
Seleziona il colore dello sfondo
TextColor
Seleziona il colore del testo
LowVideo
I successivi caratteri sono scritti a bassa luminosità.
NormVideo
Ripristina, per il testo, il valore che esso aveva all’inizio del
programma.
HighVideo
I successivi caratteri sono scritti ad alta luminosità.
Window
Apre una finestra di testo.
ReadKey
Legge carattere da tastiera senza visualizzarlo sul video.
KeyPressed
Funzione che ritorna vero se è stato premuto un tasto.
Delay
Attende per il numero di millisecondi indicati.
Tab. 16
Tabella sintassi funzioni e procedure modulo CRT
TextMode(modo);
modo: integer; modo assume uno dei valori riportati
nella tabella 14.
TextMode(Lastmode);
LastMode: word; all’avvio del programma in LastMode
viene memorizzato il modo attivo in quel momento. Quindi
la chiamata ripristina il modo iniziale.
ClrScr;
Cancella il video e pone il cursore nell’angolo in alto a
sinistra (1,1).
ClrEol;
Cancella tutti i caratteri di una riga dalla posizione del
cursore alla sua fine.
DelLine;
Cancella la riga su cui è posizionato il cursore.
InsLine;
Inserisce una linea vuota sotto a quella su cui è posizionato
il cursore.
GotoXY (x,y);
x,y:byte; Sposta il cursore alla colonna x e alla riga y.
x:=WhereX
Ritorna in x la coordinata x corrente del cursore; x tipo
byte.
y := WhereY
Ritorna in y la coordinata y corrente del cursore; y tipo
byte.
TextBackground(colore);
colore: byte; Per colore può essere usato il nome o la
costante numerica: Black (nero) = 0; Blue = 1; Green
(verde) = 2; Cyan (Ciano) = 3; Red (rosso) = 4; Magenta =
5; Brown (marrone) = 6; LightGray (Grigio chiaro) = 7.
TextColor(colore);
colore: byte; Per colore può essere usato il nome o la
costante numerica: Black (nero) = 0 ; Blue = 1; Green
(verde) = 2; Cyan (ciano) = 3; Red (rosso) = 4; Magenta =
5; Brown (marrone) = 6; LightGray (grigio chiaro) =7;
DarkGray (grigio scuro) = 8; LightBlue = 9;
LightGreen =10; LigthCyan = 11; LightRed = 12;
TextColor(colore+Blink);
LightMagenta = 13; Yellow (giallo) = 14; White
(bianco) = 15;
Con Blink i caratteri scritti dopo la chiamata di
TextColor sono lampeggianti.
LowVideo;
I caratteri scritti dopo la chiamata della procedura
LowVideo sono a bassa luminosità.
NormVideo;
Dopo la chiamata della procedura NormVideo viene
ripristinato, per il testo, il valore che esso aveva all’inizio del
programma.
HighVideo;
I caratteri scritti dopo la chiamata della procedura
HighVideo sono ad alta luminosità.
Window(x1,y1,x2,y2);
x1,y1,x2,y2 :byte.(x1,y1) angolo in alto a sinistra;
(x2,y2) angolo in basso a destra.
Car:= ReadKey;
car : char; Legge carattere da tastiera e lo assegna
alla variabile car; non viene effettuato l’eco del carattere sul
video.
Repeat Until KeyPressed;
Attende che venga premuto un tasto.
Delay(millisec);
millisec: word; millisec indica il numero di
millisecondi (approssimativo) di attesa.
Prog. 19 - Programma che utilizza alcune delle procedure e funzioni di Crt
(*USO DEL MODULO CRT - PROGRAMMA CHE CREA DUE FINESTRE DI TESTO DI
COLORE DIVERSO E INSERISCE IN ESSE SCRITTE DI VARIO COLORE *)
program crt1;
uses Crt ;
var
ch
:char;
begin
(*INIZIO PROGRAMMA PRINCIPALE*)
clrscr;
(*CANCELLA SHERMO - CURSORE A 1,1*)
gotoXY(15,2);
(*COORDINATE RIFERITE AL VIDEO INTERO*)
writeln('USO DEL MODULO CRT');
window(3,3,49,11);
(*APRE 1¦ FINESTRA*)
TextBackground(Red); clrscr;
write(' E''STATA APERTA UNA FINESTRA CON COORDINATE:');
GotoXY(12,2);
(*COORDINATE RIFERITE ALLA 1¦ FINESTRA*)
write('X1=3,Y1=3,X2=49,Y2=11');
GotoXY(2,4);
(*COORDINATE RIFERITE ALLA 1 ¦FINESTRA*)
write(' ESSA E'' COLORATA IN ROSSO - PREMERE UN TASTO');
Repeat Until Keypressed;
(*ATTENDE VENGA PREMUTO UN TASTO*)
GotoXY(2,6);
(*COORDINATE RIFERITE ALLA 1 ¦FINESTRA*)
write(' ORA VERRA APERTA UNA FINESTRA CON COORDINATE');
GotoXY(10,7);
(*COORDINATE RIFERITE ALLA 1 ¦FINESTRA*)
write('X1=38,Y1=14,X2=78,Y2=24');
GotoXY(14,8);
(*COORDINATE RIFERITE ALLA 1 ¦FINESTRA*)
writeln('PREMERE UN TASTO ');
ch:=ReadKey;
(*ATTENDE VENGA PREMUTO UN TASTO*)
window(38,14,78,24);
(*APRE 2¦ FINESTRA*)
TextBackground(Blue); clrscr;
(*COLORE DI SFONDO AZZURRO*)
TextColor(Magenta); LowVideo;
(*TESTO MAGENTA - BASSA LUMINOSITA'''*)
GotoXY(2,2);
(*COORDINATE RIFERITE ALLA 2 ¦FINESTRA*)
write('SCRITTURA CON BASSA LUMINOSITA''-MAGENTA');
TextColor(Green); HighVideo;
(*TESTO VERDE - ALTA LUMINOSITA'''*)
GotoXY(2,3);
(*COORDINATE RIFERITE ALLA 2 ¦FINESTRA*)
write('SCRITTURA CON ALTA LUMINOSITA''- VERDE');
TextColor(Red+Blink);
(*TESTO ROSSO INTERMITTANTE*)
GotoXY(2,5);
(*COORDINATE RIFERITE ALLA 2¦ FINESTRA*)
write('LA NUOVA FINESTRA E''COLORATA IN AZZURRO');
gotoXY(14,8);
(*COORDINATE RIFERITE ALLA 2¦ FINESTRA*)
TextColor(Yellow);
(*TESTO GIALLO*)
writeln('PREMERE UN TASTO');
ch:=ReadKey;
TextMode(LastMode);
(*RIPRISTINA IL MODO TESTO INIZIALE*)
end.
Osservazioni:
• Il programma lavora con video di 80 colonne x 25 righe. Dopo la chiamata di TextBackground, si
deve utilizzare un clrscr perché la finestra venga colorata completamente con il colore di
sfondo; in caso contrario verrà colorato solo il fondo dei caratteri.
• La funzione KeyPressed non può essere utilizzata più volte di seguito, in quanto non rimuove i
caratteri dal buffer di tastiera e pertanto al suo secondo uso trova già un carattere nel buffer,
anche se non si è premuto alcun tasto. Può essere usata in alternativa la funzione ReadKey.
• Al termine del programma bisogna ripristinare la modalità video iniziale. Ciò può essere fatto con la
chiamata di TextMode passando come parametro la costante LastMode in cui è appunto
memorizzata la modalità video iniziale.
15 La grafica nel TURBO-PASCAL
Il Pascal standard non contiene nessun elemento che permetta la rappresentazione di elementi grafici sul
video. Nel TURBO-PASCAL invece sono state incluse numerose funzioni grafiche di libreria. Tuttavia i
programmi che contengono tali funzioni, possono essere utilizzati solo sui Personal Computer con
sistema operativo MS-DOS.
Le funzioni grafiche di libreria del TURBO-PASCAL sono state raggruppate nel modulo Graph, che deve
essere compilato unitamente al programma realizzato per disporre delle funzioni in esso contenute.
Prima di esaminare le principali funzioni contenute nel modulo standard Graph, è bene dare alcune
definizioni valide nell’ambiente grafico.
In tale ambiente il video è visto come un insieme di punti, detti pixel, che possono essere illuminati o
meno per formare immagini grafiche. Il numero di punti, presenti sul video, che possono essere
distintamente presi in considerazione è legato sia al tipo di video che alla scheda grafica presente
all’interno del computer.
Il TURBO-PASCAL supporta molte schede grafiche con diversa risoluzione; le principali sono:
• CGA risoluzione 320 pixel orizzontali x 200 pixel verticali con possibilità di disegni fatti con 3 colori
più uno per lo sfondo.
• CGA risoluzione 640 pixel orizzontali x 200 pixel verticali con possibilità di disegni fatti con 1
colore più uno per lo sfondo.
• EGA risoluzione 640 pixel orizzontali x 350 pixel verticali con possibilità di disegni fatti con 16
colori.
• VGA risoluzione 640 pixel orizzontali x 480 pixel verticali con possibilità di disegni fatti con 16
colori.
E’ da tenere presente che per ognuna delle modalità sopra citate possono essere configurate diverse
combinazioni di risoluzione e numero di colori.
Per utilizzare le funzioni grafiche è necessario che nel software del TURBO-PASCAL siano presenti, dei
particolari file, detti driver (piloti), con estensione .BGI.
Per supportare le schede grafiche sopra descritte occorre, a seconda della modalità prescelta, uno dei
seguenti driver :
•
•
CGA.BGI per le varie modalità CGA;
EGAVGA.BGI per le modalità EGA e VGA.
Il driver adatto deve essere presente sul disco e nella giusta subdirectory anche quando si fa girare un
programma già compilato (.EXE).
I pixel sul video possono essere paragonati ai quadretti di un foglio di carta millimetrata.
L’origine del foglio è posta nell’angolo in alto a sinistra del video, tale punto corrisponde la coordinata
(0,0). Nelle varie modalità grafiche, variando il numero di pixel, cambierà anche la coordinata dell’angolo
in basso a destra. Per i tipi di risoluzione grafica visti sopra, si avranno le configurazioni riportate in figura
3:
0,0
0,0
0,0
CGA
EGA
VGA
320x200
640x350
640x480
319,199
639,349
639,479 Fig. 3
In modalità grafica esiste un cursore, non visibile, che contraddistingue un punto all’interno dell’area
attiva di disegno. Tale cursore viene definito puntatore corrente (CP) e rappresenta il punto da cui
inizieranno le rappresentazioni grafiche se la sua posizione non viene variata con valori diversi posti
all’interno delle istruzioni grafiche.
L’intero schermo può essere suddiviso in riquadri rettangolari più piccoli chiamati viewport, in tal caso,
tutti gli elementi grafici, comprese le coordinate, sono riferiti alla viewport attiva.
50
560
(0,0) VIDEO
40
40
(0,0) VIEWPORT
(51,20)
240
270
(0,0) VIEWPORT
290
(0,0) VIEWPORT
(22,16)
(26,18)
450
450
(639,479)
30
250 280
540
Fig. 4
Nella figura 4 sono evidenziate tre viewport; per ciascuna di esse sono rappresentate le coordinate
rispetto all’intero video (da utilizzare al momento della definizione della viewport), quelle invece relative
alla viewport stessa non possono essere superate quando si lavora al suo interno.
MODULO GRAPH
Nella tabella 17 sono elencate le principali funzioni e procedure incluse nel modulo graph.
Tab. 17
Tabella descrizione funzioni e procedure modulo graph
InitGraph
Pone il sistema in modalità grafica.
DetectGraph
Rileva il tipo di scheda grafica presente nel computer.
SetGraphMode
Imposta un determinato sistema grafico.
GetMaxX;
Ritorna il massimo numero di pixel orizzontali del modo grafico corrente.
GetMaxY;
Ritorna il massimo numero di pixel verticali del modo grafico corrente.
RestoreCRTMode
Riporta il video al sistema attivo prima dell’inizializzazione della grafica.
CloseGraph
Rende inattivo il sistema grafico.
ClearViewPort
Cancella la viewport attiva posizionando il puntatore corrente nell’origine
della viewport.
ClearDevice
Cancella il video posizionando il puntatore corrente in (0,0).
Line
Disegna una linea dalle coordinate (x1,y1) alle coordinate (x2,y2).
LineTo
Disegna una linea dalla posizione attuale del puntatore corrente alle
coordinate (x,y).
LineRel
Disegna una linea dalla posizione attuale del puntatore corrente fino alla
distanza indicata.
Rectangle
Disegna un rettangolo con spigolo superiore in (x1,y1) e inferiore in
(x2,y2).
Circle
Disegna un cerchio con centro in (x,y) e raggio r.
Arc
Disegna un arco di cerchio con centro in (x,y) dall’angolo iniziale
all’angolo finale.
Ellipse
Disegna un arco di ellisse con centro in (x,y) dall’angolo iniziale
all’angolo finale.
MoveTo
Sposta il puntatore corrente alle coordinate (x,y).
ImageSize
Ritorna numero di byte necessario per memorizzare un’area dello
schermo.
PutPixel
Accende un pixel alle coordinate (x,y).
GetPixel
Riporta il valore del pixel delle coordinate (x,y).
GetX
Ritorna la coordinata x del puntatore corrente.
GetY
Ritorna la coordinata Y del puntatore corrente.
OutText
Visualizza una stringa a partire dalla posizione attuale del puntatore
corrente.
OutTextXY
Visualizza una stringa a partire dalle coordinate (x,y).
SetColor
Imposta il colore del disegno.
SetBkColor
Imposta il colore dello sfondo.
Nella tabella 18 è riportata la sintassi delle procedure e funzioni grafiche sopra elencate:
Tab. 18
Tabella sintassi funzioni e procedure modulo graph
InitGraf
Driver, Modo: integer;
(Driver,Modo,Percorso);
Driver deve essere uno dei file pilota adatto alla
scheda grafica utilizzata.
Modo è una delle modalità grafiche supportate dal
Turbo Pascal.
Percorso è l’indicazione della path dove si
trovano sul disco i driver.
Vedere in fondo alla tabella alcuni valori ammessi
per Driver e Modo.
DetectGraph (Driver,Modo);
Driver, Modo: integer
La procedura rileva automaticamente il parametro
Driver e il Modo grafico presenti nella scheda
grafica.
SetGraphMode(Modo);
Modo: integer
GetMaxX;
Ritorna il massimo numero di pixel orizzontali del
modo grafico corrente;
GetMaxY;
Ritorna il massimo numero di pixel verticali del
modo grafico corrente.
RestoreCRTMode;
Riporta il video al sistema attivo prima
dell’inizializzazione della grafica.
CloseGraph;
Rende inattivo il sistema grafico.
ClearViewPort;
Cancella la viewport attiva posizionando il
puntatore corrente nell’origine della viewport.
ClearDevice;
Cancella il video posizionando il puntatore corrente
in (0,0).
Line (x1,y1,x2,y2);
x1,y1,x2,y2: integer;
LineTo(x,y);
x,y: integer; x, y sono le coordinate di un
punto.
LineRel(dx,dy);
dx,dy: integer; dx e dy rappresentano
una distanza dal puntatore corrente.
Rectangle(x1, y1, x2, y2);
x1, y1, x2, y2: integer; x1,y1 angolo
superiore sinistro; x2,y2 angolo inferiore destro.
Circle(x, y, r);
x,y: integer; r: word; x,y coordinate del
centro; r è il raggio.
Arc(x,y, ang_iniz, ang_fin,
x,y: integer; ang_iniz,ang_fin, rag: word; x,y punto
rag);
centrale dell’arco; archi in senso antiorario
espressi in gradi; 0 gradi alle ore tre.
x,y:integer;
Ellipse
ang_in,ang_fin,ra_x,ra_y:word;
x,y
(x,y,ang_in,ang_fin,ra_x,ra_y
);
punto centrale dell’arco di ellisse; ra_x è l’asse
orizzontale e ra_y quello verticale; archi in senso
antiorario espressi in gradi; 0 gradi alle ore tre.
MoveTo (x,y);
x,y :integer.
PutPixel (x,y,color);
x,y :integer; color :word; accende un
pixel del colore specificato alle coordinate x,y.
GetPixel (x,y);
x,y :integer; x e y sono le coordinate del
pixel di cui viene prelevato il colore.
GetX;
Ritorna la coordinata x (integer) del puntatore
corrente.
GetY;
Ritorna la coordinata Y (integer) del puntatore
corrente.
OutText
(nome);
OutText
Nome: string; ‘testo’ (tra apici) è una
(‘testo’);
costante stringa.
OutTextXY (x,y,stringa);
x,y :integer; stringa :string.
SetColor (colore);
Colore : word.
SetBkColor (colore);
Colore : word.
Elenco di alcuni driver grafici e dei relativi modi :
Tab. 19
Driver
DETECT
CGA
Valore
0
1
EGA
3
EGA64
4
IBM8514
6
VGA
9
Modo
Autorilevamento
CGA0 320x200 3 COLORI (verde ch.-rosso ch.-giallo)
CGA1 320x200 3 COLORI (ciano ch.-magenta ch.-bianco)
CGA2 320x200 3 COLORI (verde-rosso-marrone)
CGA3 320x200 3 COLORI (ciano-magenta-grigio ch.)
CGAHi 640x200 1 COLORE
EGALo 640x200 16 COLORI 4 PAGINE
EGAHi 640x350 16 COLORI 2 PAGINE
EGA64Lo 640X200 16 COLORI 1 PAGINA
EGA64Hi 640X350 4 COLORI 1 PAGINA
IBM8514Lo 640x480 256 COLORI
IBM8514Hi 1024x768 256 COLORI
VGALo 640x200 16 COLORI 4 PAGINE
VGAMed 640x350 16 COLORI 2 PAGINE
VGAHi 640x480 16 COLORI 1 PAGINA
15.1 - La grafica con DEV-Pascal
Apportare ai aprogrammi grafici le seguenti modifiche:
• Aprire il file sorgente.
• Sostituire nella dichiarazione delle variabili:
var
mode,driver
:integer;
il tipo integer con smallint.
• Modificare il percorso:
InitGraph(driver,mode,'d:\tp\bgi');
Con:
InitGraph(driver,mode,'');
• Salvare il programma con SAVE UNIT AS ... attribuendogli eventualmente un nome diverso.
• Avviato il programma con COMPILE AND RUN, la finestra grafica può risultare a volte coperta da
quella di testo. Ridurre quest’ultima ad icona con il pulsante con la linea
.
• Per uscire dalla modalità grafica usare il pulsante per la chiusura della finestra
16 Programmi di applicazione di grafica
Prog. 20 - Programma con rilevamento automatico della scheda
(*INIZIALIZZA LA GRAFICA CON RILEVAMENTO AUTOMATICO DELLA SCHEDA - TROVA
IL MASSIMO NUMERO DI PIXEL ORIZZONTALI E VERTICALI DISPONIBILI NEL MODO
GRAFICO RILEVATO - DISEGNA UN RETTANGOLO CON IL MASSIMO NUMERO DI PIXEL*)
program grafica1;
uses Graph,Crt ;
var
Max_O,Max_V
:integer; (*VARIABILI GLOBALI*)
procedure iniz_grafica;
var
mode,driver
:integer;
begin
driver:=DETECT;
InitGraph(driver,mode,'d:\tp\bgi');
Max_O:=GetMaxX;
.
Max_V:=GetMaxY;
Rectangle(0,0,Max_O,Max_V);
(*DISEGNA RETTANGOLO SU TUTTO LO SCHERMO*)
MoveTo (150,200);
OutText (‘PREMERE INVIO PER USCIRE DAL MODO GRAFICO’);
readln;
(*ATTENDE VENGA PREMUTO INVIO*)
end;
(*FINE PROCEDURA INIZ_GRAFICA*)
begin
RestoreCrtMode;
GoToXY(15,10) ;
write('N°.PIXEL ORIZZONTALI ',Max_O+1,'
Repeat Until Keypressed
end.
(*INIZIO PROGRAMMA PRINCIPALE*)
(*RITORNA IN MODO TESTO*)
N°.PIXEL VERTICALI ',Max_V+1);
(*ATTENDE VENGA PREMUTO UN TASTO*)
Osservazioni:
• Il programma sopra riportato inizializza il modo grafico effettuando con la procedura InitGraph
un rilievo automatico della scheda video presente nel PC. Per questo la chiamata a InitGraph
contiene il parametro driver posto precedentemente uguale a DETECT. Nel caso non si volesse
procedere ad un rilevamento automatico, driver deve essere impostato con il valore, presente
nella tabella 19, corrispondente alla scheda grafica utilizzata.
• Con le funzioni GetMaxX e GetMaxY vengono rilevati il numero massimo di pixel, orizzontali e
verticali, di cui dispone la modalità grafica.
• E’ da notare che, sempre nella stessa procedura, è presente il percorso per la ricerca del driver
grafico .BGI (EGAVGA.BGI o CGA.BGI o uno degli altri forniti con il compilatore). Si è supposto
che esso si trovi in una subdirectory denominata BGI posta a sua volta nella subdirectory TC
dove è presente anche il compilatore. Il percorso completo è quindi: C:\TC\BGI.
• Quando viene fatto girare, il programma visualizza un rettangolo che ha le dimensioni di tutto lo
schermo; al centro è posta una frase scritta in modalità grafica, utilizzando la procedura
OutText. Viene poi ripristinato il modo testo con RestoreCrtMode e vengono visualizzati i
valori, precedentemente acquisiti, del numero massimo di pixel disponibili.
• Con Repeat Until KeyPressed si attende che venga premuto un tasto prima di ritornare al
modo edit del TURBO PASCAL.
Prog. 21 - Programma che traccia assi cartesiani
(*TRACCIA GLI ASSI CARTESIANI AL CENTRO DELLO SCHERMO*)
program grafica2;
uses Graph,Crt ;
var
Max_O,Max_V
:integer;
(*VARIABILI GLOBALI*)
X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2 :integer;
procedure iniz_grafica;
var
mode,driver
:integer;
begin
driver:=DETECT;
InitGraph(driver,mode,'d:\tp\bgi');
Max_O:=GetMaxX;
Max_V:=GetMaxY;
Rectangle(0,0,Max_O,Max_V);
(*DISEGNA RETTANGOLO SU TUTTO LO SCHERMO*)
end;
(*FINE PROCEDURA INIZ_GRAFICA*)
procedure coord_assiXY ;
begin
X_x1:=40;
X_y1:=Max_V div 2 ;
X_x2:=Max_O - 40;
X_y2:=X_y1;
Y_x1:=Max_O div 2 ;
Y_y1:=40;
Y_x2:=Y_x1;
Y_y2:=Max_V - 40;
end;
procedure assi_XY ;
begin
(*FISSA GLI ESTREMI DEGLI ASSI CARTESIANI*)
(*INIZIO A 40 PIXEL DAL BORDO SUPERIORE*)
(*FINE A 40 PIXEL PRIMA DEL BORDO INFERIORE*)
(*INIZIO A 40 PIXEL DAL BORDO LATERALE SIN.*)
(*FINE 40 PIXEL PRIMA DEL BORDO LATER. DEST.*)
(*TRACCIA GLI ASSI CARTESIANI*)
coord_assiXY ;
line (X_x1,X_y1,X_x2,X_y2);
line (Y_x1,Y_y1,Y_x2,Y_y2);
end;
(*TRACCIA ASSE DELLE ASCISSE*)
(*TRACCIA ASSE DELLE ORDINATE*)
(*FINE PROCEDURA ASSI_XY*)
begin
(****INIZIO PROGRAMMA PRINCIPALE****)
iniz_grafica;
assi_xy;
repeat until KeyPressed;
CloseGraph;
end.
Osservazioni:
• Questo secondo programma, per inizializzare la grafica, utilizza una procedura uguale a quella del
Programma 18.
• Una seconda procedura (procedure assi_xy), provvede a disegnare al centro del video gli assi
cartesiani. Essa però, chiama a sua volta un’altra procedura, che fissa le coordinate iniziali e
finali degli assi cartesiani. Per porli esattamente a metà video il numero massimo dei pixel
acquisito viene diviso per due utilizzando l’operatore di divisione intera (div).
• Osservare la figura 5 per individuare gli identificatori utilizzati per le coordinate degli estremi degli
assi.
(Y_x1,Y_y1)
(X_x1,X_y1)
(X_x2,X_y2)
(Y_x2,Y_y2)
Fig. 5
Prog. 22 - Programma che crea il reticolo sullo schermo
(*TRACCIA GLI ASSI CARTESIANI AL CENTRO DELLO SCHERMO - LI RACCHIUDE IN
UN RETTANGOLO - CREA UN RETICOLO AL SUO INTERNO*)
program grafica3;
uses Graph,Crt ;
var
Max_O,Max_V
:integer;
(*VARIABILI GLOBALI*)
X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2 :integer;
procedure iniz_grafica;
var
mode,driver
:integer;
begin
driver:=DETECT;
InitGraph(driver,mode,'d:\tp\bgi');
Max_O:=GetMaxX;
Max_V:=GetMaxY;
Rectangle(0,0,Max_O,Max_V);
(*DISEGNA RETTANGOLO SU TUTTO LO SCHERMO*)
end;
(*FINE PROCEDURA INIZ_GRAFICA*)
procedure coord_asseXY (var X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2:integer);
begin
X_x1:=40;
(*INIZIO A 40 PIXEL DAL BORDO SUPERIORE*)
X_y1:=Max_V div 2 ;
X_x2:=Max_O - 40;
(*FINE 40 PIXEL PRIMA DEL BORDO INFERIORE*)
X_y2:=X_y1;
Y_x1:=Max_O div 2 ;
Y_y1:=40;
(*INIZIO A 40 PIXEL DAL BORDO LATERALE SIN.*)
Y_x2:=Y_x1;
Y_y2:=Max_V - 40;
(*FINE 40 PIXEL PRIMA DEL BORDO LATER. DEST.*)
end;
procedure assi_XY (var X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2:integer);
begin
coord_asseXY (X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2);
line (X_x1,X_y1,X_x2,X_y2);
(*TRACCIA ASSE DELLE ASCISSE*)
line (Y_x1,Y_y1,Y_x2,Y_y2);
(*TRACCIA ASSE DELLE ORDINATE*)
end;
(*FINE PROCEDURA ASSI_XY*)
procedure freccia (X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2:integer);
begin
Line(X_x2,X_y2-5,X_x2,X_y2+5);
(*DISEGNA FRECCIA SU ASSE ASCISSE*)
Line(X_x2,X_y2+5,X_x2+10,X_y2);
Line(X_x2+10,X_y2,X_x2,X_y2-5);
Line(Y_x1-5,Y_y1,Y_x1+5,Y_y1);
(*DISEGNA FRECCIA SU ASSE ORDINATE*)
Line(Y_x1+5,Y_y1,Y_x1,Y_y1-10);
Line(Y_x1,Y_y1-10,Y_x1-5,Y_y1);
end;
(*FINE PROCEDURA FRECCIA*)
procedure retic_vert (X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2:integer);
var
i,div_X,Xdis_av,Xdis_in,Y_dis
:integer;
begin
SetLineStyle(DottedLn,0,NormWidth); (*IMPOSTA TRACCIAMENTO LINEE A PUNTI*)
div_X:=(X_x2-X_x1) div 20;
(*DIVIDE L'ASSE X IN 20 PARTI*)
Xdis_av:=Y_x1; Xdis_in:=Y_x1;
(*PRIMO VALORE SULL'ASSE X*)
for i:=1 to 10
do
begin
Xdis_av:=Xdis_av+div_X; (*SI SPOSTA AVANTI SULL'ASSE X OGNI DIVISIONE*)
Line(Xdis_av,Y_Y1,Xdis_av,Y_y2); (*LINEE VERTICALI SULL'ASSE X POSIT.*)
Xdis_in:=Xdis_in-div_X; (*SI SPOSTA INDIETRO SULL'ASSE X OGNI DIVIS.*)
Line(Xdis_in,Y_Y1,Xdis_in,Y_y2); (*LINEE VERTICALI SULL'ASSE X NEGAT.*)
end;
end;
procedure retic_oriz (X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2:integer);
var
i,div_Y,Ydis_av,Ydis_in,Y_dis
:integer;
begin
div_Y:=(Y_y2-Y_y1) div 20;
(*DIVIDE L'ASSE Y IN 20 PARTI*)
Ydis_av:=X_y1; Ydis_in:=X_y1;
(*PRIMO VALORE SULL'ASSE Y*)
for i:=1 to 10
do
begin
Ydis_av:=Ydis_av+div_Y; (*SI SPOSTA AVANTI SULL'ASSE Y OGNI DIVISIONE*)
Line(X_x1,Ydis_av,X_x2,Ydis_av); (*LINEE ORIZZONT. SULL'ASSE Y POSIT.*)
Ydis_in:=Ydis_in-div_Y; (*SI SPOSTA INDIETRO SULL'ASSE Y OGNI DIVIS.*)
Line(X_x1,Ydis_in,X_x2,Ydis_in); (*LINEE ORIZZONT. SULL'ASSE Y NEGAT.*)
end;
end;
begin
(****INIZIO PROGRAMMA PRINCIPALE****)
iniz_grafica;
assi_xy (X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2);
freccia (X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2);
retic_vert (X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2);
retic_oriz (X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2);
repeat until KeyPressed;
end.
Prog. 23 - Programma per tracciamento del grafico di funzioni
(*TRACCIA GLI ASSI CARTESIANI AL CENTRO DELLO SCHERMO - LI RACCHIUDE IN UN
RETTANGOLO - DISEGNA IL GRAFICO DELLA FUNZIONE v(t)=Vmax*sin(2*π*f*t) SONO RICHIESTI IN INPUT I VALORI DI "Vmax" , "f" E IL VALORE INIZIALE E
FINALE DI "t" *)
program grafica4;
uses Graph,Crt ;
var
Max_O,Max_V,Xiniz,Xfin
:integer;
(*VARIABILI GLOBALI*)
X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2 :integer;
Val_max,f,Vmax,T0,tin,tfin,t,dt
:real;
car: char;
function seno(tempo:real):real;
(*FUNZIONE DI CUI SI DESIDERA IL GRAFICO*)
begin
seno:=Vmax*sin(2*PI*f*tempo);
end;
(*FINE FUNZIONE SENO*)
function massimo(tempo:real):real;
(*TROVA IL MASSIMO DELLA FUNZIONE*)
var
y,ymax:real;
begin
ymax:=seno(tin);
repeat
tempo:=tempo+dt;
y:=seno(tempo);
if abs(y) > abs(ymax) then ymax:=y ;
until tempo >= tfin;
massimo:=abs( ymax );
end;
(*FINE FUNZIONE MASSIMO*)
procedure iniz_grafica;
(*INIZIALIZZA LA GRAFICA*)
var
mode,driver
:integer;
begin
driver:=DETECT;
InitGraph(driver,mode,'d:\tp\bgi');
Max_O:=GetMaxX;
Max_V:=GetMaxY;
Rectangle(0,0,Max_O,Max_V);
(*DISEGNA RETTANGOLO SU TUTTO LO SCHERMO*)
end;
(*FINE PROCEDURA INIZ_GRAFICA*)
procedure coord_asseXY ;
begin
X_x1:=40;
X_y1:=Max_V div 2 ;
X_x2:=Max_O - 40;
X_y2:=X_y1;
Y_x1:=Max_O div 2 ;
Y_y1:=40;
Y_x2:=Y_x1;
Y_y2:=Max_V - 40;
end;
(*FISSA GLI ESTREMI DEGLI ASSI CARTESIANI*)
(*INIZIO A 40 PIXEL DAL BORDO SUPERIORE*)
(*FINE A 40 PIXEL PRIMA DEL BORDO INFERIORE*)
(*INIZIO A 40 PIXEL DAL BORDO LATERALE SIN.*)
(*FINE 40 PIXEL PRIMA DEL BORDO LATER. DEST.*)
procedure assi_XY ;
begin
coord_asseXY ;
line (X_x1,X_y1,X_x2,X_y2);
line (Y_x1,Y_y1,Y_x2,Y_y2);
end;
(*TRACCIA GLI ASSI CARTESIANI*)
(*TRACCIA ASSE DELLE ASCISSE*)
(*TRACCIA ASSE DELLE ORDINATE*)
(*FINE PROCEDURA ASSI_XY*)
procedure rettangolo;
(*DISEGNA IL RETTANGOLO CHE RACCHIUDE GLI ASSI*)
begin
rectangle(X_x1,Y_y1,X_x2,Y_y2);
end;
(*FINE PROCEDURA RETTANGOLO*)
procedure grafico(tempo:real);
var
xdis,ydis,num_pix_X, num_pix_Y
y, max_temp :real;
(*DISEGNA IL GRAFICO DELLA FUNZIONE*)
:integer;
begin
num_pix_X := (X_x2-Y_x1)-20;
num_pix_Y := (X_y1-Y_y1)-20;
if abs(tfin) > abs(tin) then max_temp:=abs(tfin)
else max_temp:=abs(tin);
(*SCEGLIE IL PIU''GRANDE TRA <tin> E <tfin>*)
repeat
y:=seno(tempo);
xdis:= round( Y_x1 + (tempo * num_pix_X) / (max_temp));
ydis:= round( X_y1 - (y * num_pix_Y) / (Val_max));
putPixel(xdis,ydis,yellow);
(*DISEGNA LA FUNZIONE A PUNTI*)
tempo:=tempo+dt;
until tempo>=tfin
end;
begin
(****INIZIO PROGRAMMA PRINCIPALE****)
clrscr;
(*CANCELLA LO SCHERMO*)
writeln('DISEGNA IL GRAFICO DELLA FUNZIONE v(t)=Vmax*sin(2*π*f*t) - ');
writeln('TRACCIA GLI ASSI CARTESIANI AL CENTRO DELLO SCHERMO - ');
writeln('SONO RICHIESTI IN INPUT I VALORI DI "Vmax" [V], "f" [Hz],');
writeln('IL VALORE INIZIALE E QUELLO FINALE DI "t" [s]');
writeln;
write ('INTRODURRE VALORE MASSIMO < Vmax > [V] '); readln(Vmax);
write ('INTRODURRE FREQUENZA
< f > [Hz] '); readln(f);
T0:=1/f ;
(*CALCOLA PERIODO E LO VISUALIZZA*)
writeln ('IL PERIODO E'':
',T0:10:6,' [s]');
write ('INTRODURRE TEMPO INIZIALE
[s] ');
readln(tin);
write ('INTRODURRE TEMPO FINALE
[s] ');
readln(tfin);
Dt:=T0/600;
(*CALCOLA L'INCREMENTO DELLA VARIABILE TEMPO*)
t:=tin;
(*FISSA IL VALORE DEL TEMPO INIZIALE*)
Val_Max:=massimo(t);
writeln('VALORE MAX. DELLA FUNZ. NELL''INTERV. SCELTO ',Val_max:5:3,' [V]');
gotoXY(20,15);
writeln('PREMERE UN TASTO PER PROSEGUIRE');
car:= ReadKey;
iniz_grafica;
(*INIZIALIZZA LA GRAFICA*)
assi_xy;
(*DISEGNA GLI ASSI*)
rettangolo;
(*TRACCIA UN RETTANGOLO*)
grafico(t);
(*DISEGNA IL GRAFICO*)
car:= ReadKey;
(*ATTENDE VENGA PREMUTO UN TASTO*)
CloseGraph;
(*ESCE DAL MODO GRAFICO*)
end.
Osservazioni:
• Il programma sopra riportato è stato suddiviso in procedure e funzioni, ognuna delle quali esplica
un ben preciso compito. Alcune di esse sono state impiegate anche nel programma 19.
• Si forniscono alcune precisazioni sulle funzioni e procedure utilizzate:
1- Funzione seno ( ) In essa viene dichiarata l’espressione analitica della funzione di cui si vuole
ricavare il grafico. Nell’esempio esposto è utilizzata la funzione sinusoidale v(t) = Vmax · sen(2 · p · f · t) in
cui la variabile indipendente è il tempo t. Pertanto sia la frequenza f che l’ampiezza massima Vmax sono
considerati parametri che vengono richiesti in input all’inizio del programma. Subito dopo l’introduzione
della frequenza è calcolato, e quindi visualizzato, il periodo T. Tale valore serve all’operatore per
assegnare in modo coerente il tempo iniziale e quello finale entro cui vuole essere rappresentata la
funzione.
Qualora il programmatore volesse diagrammare una funzione diversa da quella descritta, deve
semplicemente cambiare la dichiarazione della funzione, mantenendo però come variabile indipendente il
tempo ed utilizzando come parametri le stesse grandezze sopra riportate. Introduzione di nuovi o diversi
parametri richiedono interventi anche nel corpo del programma.
E’ facile ad esempio fare il grafico delle seguenti espressioni senza modificare i parametri:
• Funzione cosinusoidale:
f(t) = Vmax · cos(2 · π f · t)
• Funzione combinazione di seno e coseno:
f(t) = Vmax · [sen(2· π f · t) + cos(2· π f · t)
• Valore assoluto della funzione seno:
f(t) = Vmax · sen(2 · π f · t)
prendendo il valore assoluto della espressione si ottiene una tensione sinusoidale con la semionda
negativa ribaltata sull’asse delle ascisse, detta comunemente tensione raddrizzata a doppia semionda. In
Pascal il valore assoluto è ottenuto con la funzione abs(...).
• Combinazione della funzione seno con l’esponenziale:
f(t) = Vmax e –k t· sen(2 · π f · t)
al valore k dell’esponenziale deve assegnarsi un opportuno valore costante; in Pascal l’esponenziale e
si ottiene con la funzione exp(...).
• Combinazione delle funzioni seno e coseno con l’esponenziale:
f(t) = Vmax [·e –k1t · sen(2 · π f · t) + e –k2t cos(2 · π f · t)]
ai valori k1 e k2 degli esponenziali debbono assegnarsi opportuni valori costanti.
sen( x)
x
• Funzione del tipo f(x) =
sen( 2 ⋅ π ⋅ f ⋅ t )
f ( t ) = V max ⋅
2⋅π⋅ f ⋅t
2) Funzione massimo( ): è necessario prima di procedere alla rappresentazione grafica della funzione,
conoscere il valore massimo assoluto che essa assume all’interno dell’intervallo scelto per la sua
rappresentazione. Il motivo di tale conoscenza verrà spiegato quando si analizzeranno le modalità di
rappresentazione grafica.
Per procedere alla ricerca del massimo assoluto, ovvero il valore massimo in valore assoluto, si assegna
alla variabile Ymax, il valore che assume la funzione nel punto iniziale di rappresentazione; dopo di che,
incrementando la variabile t di piccoli intervalli, si assegnano a ymax quei valori che dovessero risultare,
di volta in volta, più grandi di quello attualmente memorizzato, presi senza segno.
3) Procedura grafico( ): la rappresentazione grafica della funzione viene fatta per punti. La zona
del video utilizzata per il disegno del grafico è la parte centrale del video. Si è stabilito, una volta tracciati
gli assi, di adoperare, al solo scopo di avere un disegno più chiaro, un numero di pixel di poco inferiore a
quello della lunghezza degli assi cartesiani stessi. Osservare la figura 6 per un riscontro delle formule
utilizzate nel programma per assegnare il numero di pixel da utilizzare nel disegno. Il numero calcolato si
riferisce al semiasse positivo sia delle ascisse che delle ordinate. Altrettanti pixel verranno utilizzati per i
semiassi negativi.
(Y_x1,Y_y1)
X_y1 = X_y2
X_y1 - Y_y1
Y_x1 = Y_x2
COORDINATE CENTRO ASSI
(Y_x1,X_y1)
(X_x1,X_y1)
(X_x2,X_y2)
(Y_x2,Y_y2)
X_x2 - Y_x1
Fig. 6
Il metodo utilizzato per il disegno della funzione usa per la rappresentazione grafica, sempre il numero
massimo di pixel, precedentemente calcolati. Per questo motivo le funzioni rappresentate, anche se
hanno ampiezze diverse, sul disegno avranno sempre la medesima altezza. La stessa cosa avviene per
l’asse delle ascisse. Tale metodo, quindi, non è adatto al confronto di funzioni con parametri diversi (il
Programma 22 utilizza invece un metodo che permette il confronto di funzioni con parametri diversi).
Per ottenere l’espansione della funzione sulla zona delimitata dal numero di pixel precedentemente
scelto, bisogna effettuare un cambio di scala.
Per le ordinate saranno messe in relazione, con una proporzione, la coordinata del punto che dovrà
essere illuminato sul video (ydis), con il valore corrente assunto dalla funzione (y) e il numero di pixel
calcolati (num_pix_Y) con il valore massimo che la funzione assume nell’intervallo in cui si vuole
rappresentare (Ymax).
Si avrà pertanto la proporzione per l’asse delle ordinate:
ydis num _ pix _ Y
=
y
Y max
da cui si ricava:
ydis =
y ⋅ num _ pix _ Y
Y max
Si può osservare dalla relazione scritta che quando la funzione raggiungerà il valore massimo, sarà y =
Ymax e quindi diverrà ydis = num_pix_Y. Pertanto col massimo valore della funzione verrà utilizzato il
massimo numero di pixel prestabiliti.
Per le ascisse saranno messe invece in relazione, con la proporzione, la coordinata del punto che dovrà
essere illuminato sul video (xdis), con il valore corrente assegnato alla variabile indipendente (x) e il
numero di pixel calcolati (num_pix_X) con il valore massimo che assumerà la variabile indipendente
(Xmax).
Si avrà pertanto la proporzione per l’asse delle ascisse:
xdis num _ pix _ X
=
x
X max
da cui si ricava:
xdis =
x ⋅ num _ pix _ X
X max
Anche in questo caso si può osservare che quando alla variabile indipendente sarà assegnato il massimo
valore, diverrà x = Xmax e quindi xdis = num_pix_X. Pertanto, col massimo valore assunto dalla variabile
indipendente, verranno utilizzati tutti i pixel fissati per l’asse delle ascisse.
Se quindi ora si fa variare la variabile indipendente x, a partire da un valore iniziale prestabilito, fino a
raggiungere un certo valore finale, assegnando ad essa piccoli incrementi, e per ogni incremento si
ricava il corrispondente valore di y, le relazioni descritte ci forniranno di volta in volta le coordinate di un
pixel che dovrà essere acceso con la funzione putpixel( ).
E’ da osservare però che le coordinate sopra calcolate, sono riferite all’origine del video grafico e cioè
l’angolo in alto a sinistra. Gli assi cartesiani utilizzati per la rappresentazione invece hanno la loro origine
al centro del video. Si deve quindi effettuare una traslazione dell’origine, sommando ai valori trovati per
xdis e ydis la distanza che intercorre tra la vecchia origine e quella nuova. Anzi per l’asse delle ordinate si
deve effettuare anche un ribaltamento dell’asse, essendo quello utilizzato dal disegno rivolto verso l’alto,
mentre quello del video grafico verso il basso.
In definitiva le espressioni precedentemente trovate divengono:
ydis = X _ y1 −
y ⋅ num _ pix _ Y
Y max
xdis = Y _ x1 +
x ⋅ num _ pix _ X
X max
avendo indicato con X_y1 la distanza dell’asse delle ascisse dall’origine del video e con Y_x1 quella
dell’asse delle ordinate (→ figura 6). Il segno meno che compare sulla prima relazione effettua il
ribaltamento dell’asse.
Nel programma, in alcuni casi, sono stati utilizzati per le variabili nomi diversi, secondo la seguente
corrispondenza:
tempo = x ;
max_tempo = Xmax;
val_max = Ymax;
E’ da osservare infine che dovendo essere le coordinate passate alla funzione putpixel( ) di tipo
intero, bisogna utilizzare la funzione round( ) per rendere di tale tipo i risultati ottenuti dalle precedenti
espressioni.
Prog. 24 – Programma che visualizza la tensione di carica di un condensatore
(*CARICA DI UN CONDENSATORE CON TENSIONE A GRADINO ALL'INGRESSO E CON
RESISTORE IN SERIE - VENGONO CALCOLATI 20 VALORI DELLA TENSIONE Vc
ASSEGNANDO L'AMPIEZZA DEL GRADINO, IL VALORE DELLA RESISTENZA E DELLA
CAPACITA' E L'INTERVALLO DI TEMPO PER OGNI MISURA - SI FA USO DI UNA
PROCEDURA CON PASSAGGIO DI PARAMETRI FORMULA UTILIZZATA
-(t/τ)
Vc=Vm x (1 - e
)
CON π=RxC
*)
program grafica5;
uses Graph,Crt;
const
Vmax= 25;
var
Vc:array[1..20] of real;
(*VARIABILI GLOBALI*)
tempo:array[1..20] of real;
X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2 : integer;
Vm,R,C,dt,tfin,tau,diff
:real;
procedure tensione(dt,tau:real);
var
i :integer;
t :real;
begin
t:=0;
for i:=1 to 20 do
begin
tempo[i]:=t;
Vc[i]:=Vm*(1- exp(-t/tau));
t:=t+dt;
end;
tfin:=t;
end;
(*VARIABILI LOCALI DELLA PROCEDURA*)
(*FINE FOR*)
(*FINE PROCEDURA TENSIONE*)
procedure iniz_grafica;
var
mode,driver :integer;
begin
driver:=DETECT;
InitGraph(driver,mode,'D:\TP\BGI');
Rectangle(0,0,GetMaxX,GetMaxY); (*DISEGNA RETTANGOLO SU TUTTO LO SCHERMO*)
end;
(*FINE PROCEDURA INIZ_GRAFICA*)
procedure assi_xy;
begin
X_x1:=80
;
X_y1:=GetMaxY-80 ;
X_x2:=GetMaxX-40
;
X_y2:=X_y1;
line (X_x1,X_y1,X_x2,X_y2);
Y_x1:=80
;
Y_y1:=40;
Y_x2:=Y_x1
;
(*COORDINATA X ORIGINE ASSE ASCISSE*)
(*COORDINATA Y ORIGINE ASSE ASCISSE*)
(*COORDINATA X FINE ASSE ASCISSE*)
(*COORDINATA Y FINE ASSE ASCISSE*)
(*ASSE DELLE ASCISSE*)
(*COORDINATA X ORIGINE ASSE ORDINATE*)
(*COORDINATA Y ORIGINE ASSE ORDINATE*)
(*COORDINATA X FINE ASSE ORDINATE*)
Y_y2:=GetMaxY-80;
line (Y_x1,Y_y1,Y_x2,Y_y2);
OutTextXY(X_x2-20,X_y2+10,'t [s]');
OutTextXY(Y_x1-60,Y_y1,'Vc [V]');
end;
procedure freccia;
begin
Line(X_x2,X_y2-5,X_x2,X_y2+5);
Line(X_x2,X_y2+5,X_x2+10,X_y2);
Line(X_x2+10,X_y2,X_x2,X_y2-5);
Line(Y_x1-5,Y_y1,Y_x1+5,Y_y1);
Line(Y_x1+5,Y_y1,Y_x1,Y_y1-10);
Line(Y_x1,Y_y1-10,Y_x1-5,Y_y1);
end;
(*COORDINATA Y FINE ASSE ORDINATE*)
(*ASSE DELLE ORDINATE*)
(*SCRIVE UNITA' SU ASSE ASCISSE*)
(*SCRIVE UNITA' SU ASSE ORDINATE*)
(*FINE PROCEDURA ASSI_XY*)
(*DISEGNA FRECCIA SU ASSE ASCISSE*)
(*DISEGNA FRECCIA SU ASSE ORDINATE*)
(*FINE PROCEDURA FRECCIA*)
procedure disegna;
var
i,Xdis,Ydis
:integer;
t,y,Xmax,Ymax
:real;
s:string[10];
begin
Xmax:=X_x2-X_x1-20 ; (*NUMERO MASSIMO PIXEL ORIZZ. USATI PER IL DISEGNO*)
Ymax:=Y_y2-Y_y1-20 ; (*NUMERO MASSIMO PIXEL VERT. USATI PER IL DISEGNO*)
MoveTo (X_x1,Y_y2) ;
(*POSIZIONA CURSORE INIZIO ASSI*)
for i:=2 to 20
do
begin
t:=X_x1+(tempo[i]*Xmax)/tfin;
(*CALCOLA L'ASCISSA*)
y:=Y_y2-(Vc[i]*Ymax)/Vmax;
(*CALCOLA L'ORDINATA*)
Xdis:=round(t)
;
Ydis:=round(y)
;
LineTo (Xdis,Ydis); (*CONGIUNGE CON TRATTI DI LINEA VALORI CALCOLATI*)
end;
(*FINE FOR*)
t:=X_x1+(tfin*Xmax)/tfin;
y:=Y_y2-(Vm*Ymax)/Vmax;
Ydis:=round(y);
SetLineStyle(DottedLn,0,NormWidth);
Line(X_x1,Ydis,round(Xmax+40),Ydis);
(*TRACCIA LINEA Vm*)
Str(Vm:3:2,s);
OutTextXY(X_X1-65,Ydis,s+' V');
Str(tfin:10:6,s);
OutTextXY(100,Y_y2+10,'tempo finale= '+s+' s');
Str(C:10:3,s);
OutTextXY(100,Y_y2+20,'
C= '+s+' µF');
Str(R:10:3,s);
OutTextXY(100,Y_y2+30,'
R= '+s+' Ω');
end;
begin
(****INIZIO PROGRAMMA PRINCIPALE****)
clrscr;
(*PULISCE LO SCHERMO*)
writeln;
writeln ('CALCOLO DELLA CARICA DI UN CONDENSATORE IN UN CIRCUITO R-C');
writeln ('VENGONO ASSEGNATI IL VALORE DELLA CAPACITA'', DELLA RESISTENZA');
writeln ('E DELLA TENSIONE DI ECCITAZIONE A GRADINO - SONO CALCOLATI');
writeln ('20 VALORI AD INTERVALLI REGOLARI DI TEMPO CON INIZIO DA t=0 ');
writeln ('secondi - ');
writeln;
write ('INTRODURRE VALORE DELLA CAPACITA''
[µF] ');
readln (C);
write ('INTRODURRE VALORE DELLA RESISTENZA
[Ω] ');
readln (R);
repeat
gotoXY(1,10);
DelLine;
(*CANCELLA LA LINEA SU CUI SI TROVA IL CURSORE*)
write ('INTRODURRE AMPIEZZA DEL GRADINO - MAX.',Vmax-5,' V - [V] ');
readln (Vm);
until Vm <= Vmax-5 ;
tau:=R*C*1E-6 ;
(*CALCOLO COSTANTE DI TEMPO*)
dt:=(6*tau)/20;
(*CONDENSATORE CARICO DOPO 6 VOLTE COSTANTE TEMPO*)
tensione(dt,tau);
iniz_grafica;
assi_xy;
freccia;
disegna;
repeat until KeyPressed;
CloseGraph;
end.
(*CALCOLA I VALORI DELLA TENSIONE DI CARICA*)
(*INIZIALIZZA LA GRAFICA*)
(*TRACCIA GLI ASSI*)
(*DISEGNA FRECCE SU ASSI*)
(*DISEGNA IL GRAFICO*)
(*CHIUDE LA MODALITA' GRAFICA*)
Osservazioni:
Il programma esposto utilizza un procedimento analogo a quello del paragrafo 10 (→ Programma 16),
per rilevare la carica di un condensatore con in serie un resistore, quando ai capi della serie è applicata
una tensione a gradino, la cui ampiezza è richiesta in input.
In questo caso però, la tensione di carica è rappresentata graficamente su un diagramma cartesiano.
Viene visualizzato altresì il tempo impiegato perché la tensione ai capi del condensatore raggiunga
l’ampiezza del gradino. Si è utilizzata la relazione pratica per cui può ritenersi che il condensatore sia
carico dopo circa 5 ÷ 6 volte il valore della costante di tempo. Si ricorda che in teoria ciò si verifica solo
per t = ∞. Infatti dalla relazione utilizzata nel programma:
Vc = Vm · (1 – e
si vede che quando t → ∞
e
−
t
−τ
) con τ = R x C
t
τ
→ 0 e quindi Vc = Vm
Nel programma vengono adoperati degli array per memorizzare i dati. La procedura tensione() calcola
e memorizza i venti valori della tensione di carica del condensatore e i relativi tempi. Tali valori sono poi
utilizzati dalla procedura disegna() che realizza la rappresentazione grafica.
Per scrivere sul video grafico in una determinata posizione è impiegata la procedura del TURBO
PASCAL OutTextXY(). Essendo tale procedura in grado di visualizzare solo stringhe, si è dovuto
effettuare prima una conversione dei dati numerici di tipo reale in stringa usando la procedura predefinita
str() (→ Paragrafo 13).
Prog. 25 - Programma che visualizza la tensione di carica di un condensatore (con τ diverse)
(*PROG13_25*)
(*CARICA DI UN CONDENSATORE CON TENSIONE A GRADINO ALL'INGRESSO E CON
RESISTORE IN SERIE - VENGONO CALCOLATI 20 VALORI DELLA TENSIONE Vc
ASSEGNANDO L'AMPIEZZA DEL GRADINO, IL VALORE DELLA RESISTENZA E DELLA
CAPACITA' E L'INTERVALLO DI TEMPO PER OGNI MISURA - SI FA USO DI UNA
PROCEDURA CON PASSAGGIO DI PARAMETRI - TRACCIA FINO A 3 GRAFICI
SOVRAPPOSTI CON DIVERSI VALORI DI RESISTENZA E CAPACITA' FORMULA UTILIZZATA
-(t/τ)
Vc=Vm x (1- e
)
CON τ=RxC
*)
program grafica6;
uses Graph,Crt;
const
Vmax= 25;
var
Vc:array[1..20] of real;
tempo:array[1..20] of real;
R: array [1..3] of real;
C: array [1..3] of real;
tau: array [1..3] of real;
dt: array [1..3] of real;
conta,i,K :integer;
car :char;
X_x1,X_y1,X_x2,X_y2,Y_x1,Y_y1,Y_x2,Y_y2
Vm,tfin,tau_max,diff,Xmax,Ymax
procedure tensione(dt,tau:real);
var
i :integer;
t :real;
(*VARIABILI GLOBALI*)
: integer;
:real;
(*VARIABILI LOCALI DELLA PROCEDURA*)
begin
t:=0;
for i:=1 to 20 do
begin
tempo[i]:=t;
Vc[i]:=Vm*(1- exp(-t/tau));
t:=t+dt;
end;
end;
(*FINE FOR*)
(*FINE PROCEDURA TENSIONE*)
procedure iniz_grafica;
var
mode,driver :integer;
begin
driver:=DETECT;
InitGraph(driver,mode,'D:\TP\BGI');
Rectangle(0,0,GetMaxX,GetMaxY); (*DISEGNA RETTANGOLO SU TUTTO LO SCHERMO*)
end;
(*FINE PROCEDURA INIZ_GRAFICA*)
procedure assi_xy;
begin
X_x1:=80
;
(*COORDINATA X ORIGINE ASSE ASCISSE*)
X_y1:=GetMaxY-80 ;
(*COORDINATA Y ORIGINE ASSE ASCISSE*)
X_x2:=GetMaxX-40
;
(*COORDINATA X FINE ASSE ASCISSE*)
X_y2:=X_y1;
(*COORDINATA Y FINE ASSE ASCISSE*)
line (X_x1,X_y1,X_x2,X_y2);
(*ASSE DELLE ASCISSE*)
Y_x1:=80
;
(*COORDINATA X ORIGINE ASSE ORDINATE*)
Y_y1:=40;
(*COORDINATA Y ORIGINE ASSE ORDINATE*)
Y_x2:=Y_x1
;
(*COORDINATA X FINE ASSE ORDINATE*)
Y_y2:=GetMaxY-80;
(*COORDINATA Y FINE ASSE ORDINATE*)
line (Y_x1,Y_y1,Y_x2,Y_y2);
(*ASSE DELLE ORDINATE*)
OutTextXY(X_x2-20,X_y2+10,'t [s]');
(*SCRIVE UNITA' SU ASSE ASCISSE*)
OutTextXY(Y_x1-60,Y_y1,'Vc [V]');
(*SCRIVE UNITA' SU ASSE ORDINATE*)
end;
(*FINE PROCEDURA ASSI_XY*)
procedure freccia;
begin
Line(X_x2,X_y2-5,X_x2,X_y2+5);
Line(X_x2,X_y2+5,X_x2+10,X_y2);
Line(X_x2+10,X_y2,X_x2,X_y2-5);
Line(Y_x1-5,Y_y1,Y_x1+5,Y_y1);
Line(Y_x1+5,Y_y1,Y_x1,Y_y1-10);
Line(Y_x1,Y_y1-10,Y_x1-5,Y_y1);
end;
(*DISEGNA FRECCIA SU ASSE ASCISSE*)
(*DISEGNA FRECCIA SU ASSE ORDINATE*)
(*FINE PROCEDURA FRECCIA*)
procedure disegna;
var
i,Xdis,Ydis
:integer;
t,y
:real;
begin
Xmax:=X_x2-X_x1-20 ; (*NUMERO MASSIMO PIXEL ORIZZ. USATI PER IL DISEGNO*)
Ymax:=Y_y2-Y_y1-20 ; (*NUMERO MASSIMO PIXEL VERT. USATI PER IL DISEGNO*)
MoveTo (X_x1,Y_y2) ;
(*POSIZIONA CURSORE INIZIO ASSI*)
for i:=2 to 20
do
begin
t:=X_x1+(tempo[i]*Xmax)/tfin;
(*CALCOLA L'ASCISSA*)
y:=Y_y2-(Vc[i]*Ymax)/Vmax;
(*CALCOLA L'ORDINATA*)
Xdis:=round(t)
;
Ydis:=round(y)
;
LineTo (Xdis,Ydis); (*CONGIUNGE CON TRATTI DI LINEA VALORI CALCOLATI*)
end;
(*FINE FOR*)
end;
(*FINE PROCEDURA DISEGNA*)
procedure scrivi(R,C:real;K:integer);
var
s:string[12];
begin
Str(C:10:3,s);
OutTextXY(K,Y_y2+20,'C= '+s+' µF');
Str(R:10:3,s);
OutTextXY(K,Y_y2+30,'R= '+s+'
end;
Ω');
procedure linea;
var
s:string[12];
t,y
:real;
Ydis,Xdis :integer;
begin
t:=X_x1+(tfin*Xmax)/tfin;
y:=Y_y2-(Vm*Ymax)/Vmax;
Ydis:=round(y);
SetLineStyle(DottedLn,0,NormWidth);
Line(X_x1,Ydis,round(Xmax+40),Ydis);
Str(Vm:3:2,s);
OutTextXY(X_x1-65,Ydis,s+' V');
Str(tfin:10:6,s);
OutTextXY(100,Y_y2+10,'tempo finale= '+s+'
end;
(*FINE PROCEDURA SCRIVI*)
(*TRACCIA LINEA Vm*)
s');
(*FINE PROCEDURA LINEA*)
begin
(****INIZIO PROGRAMMA PRINCIPALE****)
clrscr;
(*PULISCE LO SCHERMO*)
writeln;
writeln ('CALCOLO DELLA CARICA DI UN CONDENSATORE IN UN CIRCUITO R-C');
writeln ('VENGONO ASSEGNATI IL VALORE DELLA CAPACITA'', DELLA RESISTENZA');
writeln ('E DELLA TENSIONE DI ECCITAZIONE A GRADINO - SONO CALCOLATI');
writeln ('20 VALORI AD INTERVALLI REGOLARI DI TEMPO CON INIZIO DA t=0 ');
writeln ('secondi - POSSONO ESSERE INTRODOTTI VALORI DIVERSI DI ');
writeln ('RESISTENZA E CAPACITA'' (MASSIMO TRE COPPIE DI VALORI)');
conta:=0;
repeat
writeln;
conta:=conta+1;
write ('INTRODURRE VALORE DELLA CAPACITA''
[µF] ');
readln (C[conta]);
write ('INTRODURRE VALORE DELLA RESISTENZA
[Ω] ');
readln (R[conta]);
write('INTRODURRE ALTRI VALORI? (s/n) ');
car:=ReadKey;
until ( (conta > 2) or ( (car <> 's') and (car <> 'S') ) );
repeat
gotoXY(1,20);
DelLine;
(*CANCELLA LA LINEA SU CUI SI TROVA IL CURSORE*)
write ('INTRODURRE AMPIEZZA DEL GRADINO - MAX.',Vmax-5,' V - [V] ');
readln (Vm);
until Vm <= Vmax-5 ;
tau_max:=0;
for i:=1 to conta do
begin
tau[i]:=R[i]*C[i]*1E-6 ;
(*CALCOLO COSTANTE DI TEMPO*)
if tau[i]>tau_max then tau_max:=tau[i]; (*TROVA IL PIU' GRANDE DEI TAU*)
end;
tfin:=6*tau_max;
(*CONDENSATORE CARICO DOPO 6 VOLTE COSTANTE TEMPO*)
iniz_grafica;
(*INIZIALIZZA LA GRAFICA*)
assi_xy;
(*TRACCIA GLI ASSI*)
freccia;
K:=50;
(*POSIZIONE INIZIALE PER SCRIVERE*)
for i:=1 to conta do
begin
dt[i]:=(6*tau[i])/20; (*CALCOLA INCREMENTI DELLA VARIABILE INDIPENDENTE*)
tensione(dt[i],tau[i]);
(*TROVA I 20 VALORI DELLA TENSIONE DI CARICA*)
disegna;
(*DISEGNA IL GRAFICO*)
scrivi(R[i],C[i],K);
(*SCRIVE I VALORI DELLE RES. E DEI COND.*)
K:=K+180;
(*SPOSTA LA POSIZIONE INIZIALE DI SCRITTURA*)
end;
linea;
(*TRACCIA LA LINEA DELLA Vmax*)
repeat until KeyPressed;
CloseGraph;
(*CHIUDE LA MODALITA' GRAFICA*)
end.
Osservazioni:
Nel programma possono confrontarsi fino a tre diversi grafici della carica del condensatore. Il numero è
limitato solamente per motivi di chiarezza rappresentativa.
17 Uso dei puntatori
Verrà ora dato un breve cenno sull’utilizzazione dei puntatori nel TURBO-PASCAL.
Come si è detto un puntatore non è altro che l’indirizzo di un dato presente in memoria. L’importanza
dell’uso dei puntatori risiede nel fatto che con essi è possibile riservare memoria per i dati in modo
dinamico, ovvero nel momento in cui essa effettivamente serve. Con gli altri tipi di dati invece, all’inizio
del programma, quando viene effettuata la dichiarazione delle costanti, delle variabili, ecc., viene
riservato dal compilatore lo spazio necessario per contenere esattamente i tipi di dati dichiarati.
Per meglio comprendere quanto detto, si crei una lista di nomi memorizzata in una struttura di tipo array.
In questo caso dovrà essere nota a priori la lunghezza della lista o, quanto meno, dovrà fissarsi una
lunghezza massima oltre la quale non andare. Questo perché nella dichiarazione dell’array dovrà essere
incluso il numero massimo di elementi che esso deve contenere.
Se ora la lista di nomi supera il limite imposto, dovrà essere variata la dichiarazione dell’array compilando
di nuovo il programma. Utilizzando i puntatori, ciò non è necessario perché di volta in volta viene
riservata la memoria occorrente per il nuovo nome da aggiungere alla lista. Naturalmente il processo può
continuare fin quando è disponibile memoria libera.
La definizione dei puntatori deve essere effettuata, prima con una dichiarazione di tipo (type), e dopo,
dichiarando la variabile tipo puntatore:
type
dato = tipo_dato;
tipo_puntatore = ^dato;
var
variabile_puntatore : tipo_puntatore;
Operata la dichiarazione si procede all’assegnazione di un indirizzo effettivo al puntatore utilizzando la
procedura:
new (variabile_puntatore);
Ora è possibile porre nella posizione di memoria puntata da variabile_puntatore un dato del tipo
tipo_dato. E’ altresì possibile attribuire alla variabile puntatore un valore nullo utilizzando la parola
riservata nil:
variabile_puntatore := nil;
Per liberare la memoria precedentemente occupata può essere usata la procedura:
dispose (variabile_puntatore);
Un esempio chiarirà quanto esposto. Si riserva in memoria lo spazio per un dato di tipo integer; e si
assegna alla variabile puntatore creata, un valore introdotto da tastiera; tale valore viene poi visualizzato
referenziandolo con la variabile puntatore.
Prog. 26 – Programma che utilizza i puntatori
(*SI INTRODUCE UN NUMERO INTERO DA TASTIERA - SI CREA UNA VARIABILE PUNTATORE
- SI VISUALIZZA IL NUMERO REFERENZIANDOLO CON IL PUNTATORE*)
program punt1;
type
numero = integer;
punta_num=^numero;
var
numero1,numero2 :integer;
var_punt:punta_num;
begin
write ('introduci un numero intero ');
readln (numero1);
new(var_punt);
var_punt^:=numero1;
writeln('il numero introdotto è
', var_punt^);
end.
La spiegazione di alcune delle righe del programma è la seguente:
type
numero = integer
punta_num=^numero
var_punt: punta_num
new(var_punt);
var_punt^ := numero1
writeln('...',
var_punt^);
Si definisce numero come tipo integer;
Si definisce punta_num come tipo puntatore che punta a numero;
Viene definita la variabile puntatore var_punt;
La procedura assegna un indirizzo di memoria a var_punt;
Si pone nello spazio di memoria allocato, puntato da var_punt, il valore
integer introdotto da tastiera (ovvero numero1);
Si visualizza il numero referenziandolo con il puntatore.
Utilizzando i puntatori si realizzI ora un programma che permetta di creare un elenco di nomi, lungo quanto si vuole.
Il programma, terminata l’introduzione dei nomi da tastiera, visualizzerà l’elenco in ordine inverso a quello
dell’immissione.
Per la realizzazione dell’elenco si userà una struttura dati di tipo record con due campi (→ paragrafo 11). Nel primo
verrà memorizzato il nome di volta in volta introdotto da tastiera, mentre nel secondo verrà memorizzato il puntatore
che punta al record successivo. Si crea cioè quella che comunemente viene definita lista. Ogni nuovo nome viene
introdotto sempre in testa alla lista. Nel campo del puntatore del primo record utilizzato, insieme con il primo nome,
viene introdotto un puntatore nullo (nil). Tale record diviene, dopo l’inserimento di altri nomi, l’ultimo della lista e, ad
ogni nuova introduzione, viene spinto sempre più lontano dalla testa della lista. Tale configurazione è ben
evidenziata nella figura 7:
ULTIMO RECORD
INTRODOTTO
PUNT_INIZIO
3° NOME
ULTIMO
PUNTATORE
CREATO
CAMPO
CAMPO
NOME PUNTATORE
1° RECORD
INTRODOTTO
2° NOME
TESTA DELLA LISTA
1° NOME
NIL
CODA DELLA LISTA
Fig. 7
Il listato del programma è il seguente:
Prog. 27 – Programma che utilizza i puntatori (con record)
(*SI CREA UN ELENCO DI NOMI, INTRODOTTI DA TASTIERA, SENZA PREFFISSARNE LA
LUNGHEZZA - L'INTRODUZIONE DEI NOMI TERMINA DIGITANDO LA LETTERA f - VIENE
POI VISUALIZZATO L'ELENCO IN ORDINE INVERSO A QUELLO D'INTRODUZIONE*)
program punta2;
type
punta_elenco=^elenco;
elenco = record
nome: string[15];
punta_seguente:punta_elenco;
end;
var
var_punt,punt_inizio:punta_elenco;
nuovo_nome:string[15];
begin
writeln('PER TERMINARE DIGITARE LA LETTERA
punt_inizio:=nil;
repeat
write ('introduci un nome ');
readln (nuovo_nome);
if nuovo_nome <> 'f' then
begin
new(var_punt);
var_punt^.nome:=nuovo_nome;
var_punt^.punta_seguente:=punt_inizio;
end;
punt_inizio:=var_punt;
until nuovo_nome = 'f';
f ');
writeln ('ELENCO NOMI');
while var_punt <> nil do
begin
nuovo_nome:= var_punt^.nome;
writeln('nome ', nuovo_nome);
var_punt:= var_punt^.punta_seguente;
end;
end.
La spiegazione delle parti più significative del programma è la seguente:
type
punta_elenco=^elenco;
elenco = record
nome: string[15];
punta_seguente:punta_elenco;
nuovo_nome:string[15];
punt_inizio:=nil;
repeat .... until nuovo_nome = 'f';
if nuovo_nome <> 'f' then...
var_punt^.nome:=nuovo_nome;
var_punt^.punta_seguente:=punt_inizio;
while var_punt <> nil do ...
nuovo_nome:= var_punt^.nome;
var_punt:= var_punt^.punta_seguente;
Viene dichiarato il tipo puntatore al record.
Viene dichiarato il tipo record con due campi,
uno di tipo stringa e l’altro di tipo puntatore.
Il nome è una stringa lunga al massimo 15
caratteri.
Al puntatore del primo record è assegnato il
valore nullo (nil).
L’introduzione dei nomi continua fin quando non
si digita una ‘f’.
Solo se è introdotto un nome diverso da ‘f’
viene inserito nell’elenco.
Con tale sintassi si accede attraverso la variabile
puntatore ai campi del record.
Fin quando non viene trovato un puntatore nullo
si procede all’elenco dei nomi.
Si preleva, attraverso il puntatore, il nome
presente nel primo campo.
Si preleva, attraverso il puntatore, il nome
presente nel secondo campo; esso è il puntatore
al record successivo.
18 Programmi applicativi
Sono esposti di seguito altri programmi svolti, relativi ad alcuni degli argomenti trattati.
Prog. 28 - Programma con While…do (filtro passa-basso)
(*PROGRAMMA DI ESEMPIO SULL'UTILIZZAZIONE DELLA STRUTTURA ITERATIVA
WHILE ... DO - CALCOLA LA FREQUENZA DI TAGLIO PER UN FILTRO
PASSA BASSO DI TIPO R-C FISSATO IL VALORE DELLA CAPACITA',RIPETENDO IL
CALCOLO PER DIVERSI VALORI DI R FINO A QUANDO NON SI PONE R=0 UTILIZZA LA FORMULA:
1
Freq = 
2 x π x R x C
*)
program while_do;
const
pigreco = 3.141592;
var
Res, Cap, Freq : real;
begin
writeln;
writeln ('CALCOLO DELLA FREQUENZA DI TAGLIO PER FILTRO PASSA BASSO R-C ');
writeln ('
RIPETE IL CALCOLO PER VARI VALORI DI RESISTENZA');
writeln;
write ('SCEGLIERE IL VALORE DELLA CAPACITA'' [µF] '); readln (Cap);
writeln ('PER TERMINARE INSERIRE R=0 ');
writeln;
Res:=1 ; (* PONE Res DIVERSO DA ZERO IN MODO CHE SIA VERA LA CONDIZIONE
QUANDO SI ENTRA NEL WHILE...DO *)
while res <> 0 do
begin
writeln;
write ('SCEGLIERE IL VALORE DELLA RESISTENZA [Ω] '); readln (Res);
if Res <> 0 then (*NON ESEGUE IL CALCOLO SE Res=0*)
begin
writeln;
Freq := 1/(2*pigreco*Res*Cap*1E-6);
writeln ('LA FREQUENZA DI TAGLIO DEL FILTRO E'' ',Freq:9:4,' Hz');
end;
end;
end.
Osservazioni:
Nel listato sopra riportato si notino gli aspetti più significativi: prima di entrare nel ciclo while...do si
deve essere sicuri che la condizione sia vera; ciò nel programma è stato fatto assegnando alla variabile
Res un valore tale che renda sicuramente vera la condizione. All’interno del ciclo è posto un if...then:
serve ad evitare che quando si pone Res = 0 venga effettuata, utilizzando la formula della frequenza,
una divisione per zero. Nella formula il valore della capacità viene moltiplicato per 10-6 ( 1 E-6) per
trasformarlo in farad. Si esce dal loop (ciclo) quando la condizione diviene vera (Res = 0)
Si ripete qui lo stesso programma precedente utilizzando però la struttura repeat...until in modo da
mettere maggiormente in rilievo le differenze che esistono tra i due cicli.
Prog. 29 – Programma con repeat…until (filtro passa basso)
(*PROG13_29*)
(* PROGRAMMA DI ESEMPIO SULL'UTILIZZAZIONE DELLA STRUTTURA ITERATIVA
REPEAT...UNTIL - CALCOLA LA FREQUENZA DI TAGLIO PER UN FILTRO
PASSA BASSO DI TIPO R-C FISSATO IL VALORE DELLA CAPACITA',RIPETENDO IL
CALCOLO PER DIVERSI VALORI DI R FINO A QUANDO NON SI PONE R = 0 UTILIZZA LA FORMULA:
1
Freq = 
2 x π x R x C
*)
program repeat_until;
const
pigreco = 3.141592;
var
Res, Cap, Freq : real;
begin
writeln;
writeln ('CALCOLO DELLA FREQUENZA DI TAGLIO PER FILTRO PASSA BASSO R-C ');
writeln ('
RIPETE IL CALCOLO PER VARI VALORI DI RESISTENZA');
writeln;
write ('SCEGLIERE IL VALORE DELLA CAPACITA'' [µF] '); readln (Cap);
writeln ('PER TERMINARE INSERIRE R=0 ');
writeln;
repeat
writeln;
write ('SCEGLIERE IL VALORE DELLA RESISTENZA [Ω] '); readln (Res);
if Res <> 0 then (*NON ESEGUE IL CALCOLO SE Res=0*)
begin
writeln;
Freq := 1/(2*pigreco*Res*Cap*1E-6);
writeln ('LA FREQUENZA DI TAGLIO DEL FILTRO E'' ',Freq:9:4,' Hz');
end;
until Res = 0 (* se Res=0 esce *)
end.
Osservazioni:
Nell’esempio sopra riportato si osservi come ora non è più necessario assegnare un valore
predeterminato alla variabile prima di entrare nel ciclo. Esso viene eseguito almeno una volta. Si esce
ora dal loop quando la condizione è vera (Res = 0).
A differenza del while...do, se ora tra repeat e until è posto un blocco di istruzioni, invece di una
sola, non è necessario inserire il begin...end che le racchiuda.
Prog. 30 - Programma con for…to…do (filtro passa basso)
(*PROGRAMMA DI ESEMPIO SULL'UTILIZZAZIONE DELLA STRUTTURA ITERATIVA
FOR ... TO - CALCOLA 19 (2 DECADI) VALORI DELL'ATTENUAZIONE IN MODULO
PER UN FILTRO PASSA BASSO DI TIPO R-C FISSATO IL VALORE DELLA CAPACITA',
DELLA RESISTENZA E LA FREQUENZA DI PARTENZA. OGNI VOLTA INCREMENTA
LA FREQUENZA DI UN VALORE PARI A QUELLA INIZIALE (PER 10 VOLTE) E
POI CON VALORI PARI A QUELLA INIZIALE PER 10 (PER 9 VOLTE), DESCRIVENDO
COSI' DUE DECADI UTILIZZA LA FORMULA:
Vu
1
Att=  = 
Vi
√(1+(2*π*f*R*C)2)
*)
program for_to;
const
pigreco = 3.141592;
var
i
:integer;
Att, Res, Cap, Freq_ini, Freq : real;
begin
writeln;
writeln ('CALCOLO DI 19 VALORI (2 DECADI) DELL''ATTENUAZ. IN MODULO ');
writeln ('PER FILTRO PASSA BASSO R-C PARTE DA UNA FREQUENZA INIZIALE');
writeln ('ASSEGNATA E INCREMENTA LA FREQUENZA DI 1/10 DEL VALORE INIZIALE');
writeln ('SONO RICHIESTI I VALORI DELLA RESISTENZA E DEL CONDENSATORE');
writeln;
write ('SCEGLIERE IL VALORE DELLA CAPACITA'' [µF] '); readln (Cap);
write ('SCEGLIERE IL VALORE DELLA RESISTENZA [Ω] '); readln (Res);
writeln;
Freq := 1/(2*pigreco*Res*Cap*1E-6);
writeln ('LA FREQUENZA DI TAGLIO DEL FILTRO E'' ',Freq:9:4,' Hz');
writeln;
write ('FREQUENZA INIZIALE
[Hz] '); readln (Freq_ini);
writeln;
Freq:=Freq_ini;
for i:=1 to 19 do
begin
Att:=1/(sqrt(1+sqr(2*pigreco*Freq*Res*Cap*1E-6)));
writeln ('FREQUENZA ',Freq:12:3,' Hz
Att. ',Att:5:3);
Freq:=Freq+Freq_ini ;
if i=9 then
begin
Freq_ini:=Freq_ini*10;
end;
end; (*fine del loop for...do*)
end.
PROGRAMMI PROPOSTI
1. Introdurre da tastiera una serie di 5 numeri con virgola, trovare il più grande e il più
piccolo, e visualizzarli sul video preceduti da opportuni messaggi.
1. Introdurre da tastiera una serie di 10 numeri interi, eseguirne la media aritmetica e
visualizzare il risultato sul video.
2. Assegnati in input i valori di 3 resistori scrivere un programma che trovi la corrente che
scorre in ciascuno di essi, se sono posti in parallelo ed alimentati con una tensione
continua assegnata anche essa da input.
3. Trovare la tensione ai capi di 3 resistori posti in serie alimentati da una tensione continua
assegnata in input, insieme ai valori dei tre resistori.
4. Scrivere un programma che simuli il funzionamento delle porte EX-OR e EX-NOR in
modo tale che, scelto il tipo di porta ed assegnati in input gli stati logici degli ingressi,
visualizzi sul video il valore logico dell’uscita.
5. Assegnati in input i valori di 3 resistori e una tensione continua, scrivere un programma
che trovi la potenza dissipata su ciascuno di essi.
6. Scrivere un programma che calcoli la tensione ai capi di un generatore reale che fornisce
a vuoto V0 = 5 V. e che abbia una resistenza interna Ri = 0.1 Ω, al variare di un carico
resistivo, con valore assegnato in input, ad esso connesso.
19 Tabelle riassuntive
Vengono qui raggruppate le tabelle riassuntive delle principali funzioni, procedure e degli operatori e
delle strutture utilizzate nel TURBO-PASCAL:
PROCEDURE DI INPUT E OUTPUTread (num);
readln (num);
write ( alfa );
writeln ( alfa );
write (‘messaggio’, alfa
);
writeln (‘messaggio’, alfa
);
OPERATORI ARITMETICI
Tipo
di
operazione
somma
sottrazione
divisione
modulo
divisione
moltiplicazione
OPERATORI SUI BIT
Tipo di
operazione
and
or
or esclusivo
Operatore
+
div
mod
/
*
Operatore
and
or
xor
not
shift a sinistra
not
shl
shift a destra
shr
Legge un dato da tastiera e lo assegna alla variabile
num.
Legge un dato da tastiera, lo assegna alla variabile num
ed effettua un salto riga.
Visualizza su video il valore della variabile alfa.
Visualizza su video il valore della variabile alfa ed
effettua un salto di riga.
Visualizza su video il testo posto tra apici e il valore
della variabile alfa.
Visualizza su video il testo posto tra apici, il valore della
variabile alfa ed effettua un salto di riga.
Tipo
dato
interi
reali
interi
reali
interi
interi
interi
reali
interi
reali
di
o
o
quoziente intero
resto della divisione tra interi
o
o
Operazione effettuata
Esegue la and tra i bit corrispondenti di due interi.
Esegue la or tra i bit corrispondenti di due interi.
Esegue un or esclusivo tra i bit corrispondenti di due
interi.
Esegue la not su ogni bit di un intero.
Sposta a sinistra i bit di un intero, inserendo a destra degli
zeri.
Sposta a destra i bit di un intero, inserendo a sinistra degli
zeri.
OPERATORI LOGICI
Tipo di
operazione
and
Operatore
and
or
or
or esclusivo
xor
not
not
OPERATORI RELAZIONALI
Tipo
di
operazione
uguale
diverso
maggiore
minore
maggiore
o
uguale
minore o uguale
Simbolo
Operazione effettuata
Esegue la and tra due dati di tipo boolean. Il risultato è vero
solo se sono veri ambedue i dati.
Esegue la or tra due dati di tipo boolean. Il risultato è vero
se almeno uno dei due dati è vero.
Esegue un or esclusivo tra due dati di tipo boolean. Il
risultato è vero se i due dati sono uno falso e l'altro vero o
viceversa.
Esegue la not su un dato di tipo boolean. Il risultato è vero
se il dato è falso e viceversa.
Operazione effettuata
=
< >
>
<
> =
Confronta l'eguaglianza tra due dati.
Controlla se un dato è diverso dall'altro.
Controlla se un dato è maggiore dell'altro.
Controlla se un dato è minore dell'altro.
Controlla se un dato è maggiore o uguale all'altro.
< =
Controlla se un dato è minore o uguale all'altro.
FUNZIONI ARITMETICHE STANDARD
Tipo
Descrizione
Sin()
Cos()
ArcTan()
Sqr()
Esegue il seno dell’argomento posto tra le parentesi.
Esegue il coseno dell’argomento posto tra le parentesi.
Esegue l’arcotang. dell’argomento posto tra le parentesi.
Esegue il quadrato dell’argomento posto tra le parentesi.
Sqrt()
Esegue la radice quadrata dell’argomento posto tra le
parentesi.
Restituisce il valore assoluto dell’argomento posto tra le
parentesi.
Restituisce la parte intera dell’argomento posto tra le
parentesi.
Restituisce la parte frazionaria dell’argomento posto tra le
parentesi.
Esegue il logaritmo naturale dell’argomento posto tra le
parentesi.
Esegue l’esponenziale dell’argomento posto tra le
parentesi.
Restituisce il valore 3.14159265.......(il tipo restituito è reale).
Abs()
Int()
Frac()
Ln()
Exp()
Pi
FUNZIONI DI CONVERSIONE
Tipo
Descrizione
Round(x)
Trunc(x)
Chr(x)
Ord(x)
Arrotonda il valore x real con uno di tipo longint.
Tronca il valore x real restituendo un longint.
Restituisce il carattere ASCII corrispondente a x.
Restituisce un valore intero relativo al tipo ordinale x.
Tipo
argom.
reale
reale
reale
intero
reale
reale
o
intero
reale
reale
o
reale
reale
reale
Tipo
argom.
reale
reale
intero
intero
reale
o
LE STRUTTURE
a) if condizione
then istruzione...
b) if condizione
istruz. 1)
then
istruz.
1
(o
blocco
else
istruz.
2
(o
blocco
istruz. 2)
c)
of
1
2
case
espressione...
etichetta
case
:
istruzione
etichetta
case
:
istruzione
..........................................
etichetta
case
:
istruzione
N
end;
d) case espressione... of
etichetta
case
:
istruzione
1
etichetta
case
:
istruzione
2
..........................................
etichetta
case
:
istruzione
N
else
istruzione M
end;
e) while condizione do istruzione (o blocco
istruzioni)
f) repeat istruzione
until condizione.
(o
g)
for
indice
espressione2
do ...
:=
h)
for
indice
espressione2
do.
:=
blocco
istruzioni)
espressione1
espressione1
to
downto
Se
si
verifica
tale
condizione allora esegui
istruzione.
Se
si
verifica
tale
condizione allora esegui
istruzione 1 altrimenti
istruzione 2.
Se espressione è uguale ad
etichette
una
delle
case esegui la relativa
istruzione.
Se espressione è uguale ad
etichette
una
delle
case esegui la relativa
istruzione.
Altrimenti
istruzione M.
esegui
Mentre è verificata la
esegui
condizione
istruzione (o blocco
istruzioni).
Ripeti istruzione (o blocco
istruzioni) fino a quando
non è vera la condizione
seguente.
Per indice che varia dal
valore espressione1 al
espressione2
valore
esegui quanto segue ed
incrementa indice di uno.
Per indice che varia dal
valore espressione1 al
valore
espressione2
esegui quanto segue e
decrementa indice di uno.
PROCEDURE E FUNZIONI PER LA GESTIONE DEI FILE
ASSIGN(elenco,'A:nomi.txt')
Assegna al nome fisico del file con cui verrà
registrato sul disco ('A: nomi.txt'), il nome logico
elenco .
REWRITE(elenco)
Crea il file elenco registrandolo sul disco A: con il
nome ‘nomi.txt'. Se il file già esiste, il vecchio
contenuto viene perso.
RESET(elenco)
Apre il file elenco per la lettura. Il puntatore del file
punterà al primo dato registrato nel file.
CLOSE(elenco)
Chiude il file precedentemente aperto per la lettura o
la scrittura. Questo comando, in caso di scrittura,
svuota anche il buffer registrando i dati in esso
eventualmente presenti e non ancora scritti su
disco.
WRITE(elenco,cognome)
Scrive la variabile cognome nel file elenco. Il
puntatore del file incrementa automaticamente di
una posizione.
READ(elenco,città)
Legge un dato dal file elenco e lo assegna alla
variabile città. Il puntatore automaticamente
incrementa di una posizione.
EOF(elenco)
Controlla che non si sia raggiunta la fine del file.
FILESIZE(elenco)
Restituisce il numero di dati presenti nel file.
SEEK(elenco,numero)
Posiziona il puntatore sul dato del file elenco la cui
posizione è espressa da "numero".
SEEK(elenco,FILESIZE(elenco))
Posiziona il puntatore alla fine del file elenco.
Questa funzione serve per aggiungere in coda nuovi
dati ad un file già esistente. Il file deve essere
aperto, in tal caso, con la funzione RESET.
PROCEDURE E FUNZIONI PER IL TRATTAMENTO DI STRINGHE
Funzione
Descrizione
Length
Restituisce la lunghezza di una stringa.
Concat
Unisce due o più stringhe.
Copy
Restituisce una stringa (sottostringa) che è una parte di un’altra
stringa.
Effettua la ricerca di una stringa (sottostringa) all’interno di un’altra
Pos
stringa.
Procedura
Descrizione
Str
Converte un intero o un reale in una stringa.
Val
Converte una stringa (se di tipo numerico) in un numero di tipo
intero o reale.
Delete
Cancella un sottostringa da una stringa.
Insert
Inserisce una sottostringa in una stringa.
FUNZIONI E PROCEDURE DEL MODULO CRTTextMode
Attiva il modo di testo selezionato.
ClrScr
Cancella il video e pone il cursore nell’angolo in alto a sinistra
(1,1).
ClrEol
Cancella tutti i caratteri di una riga dalla posizione del cursore alla
sua fine.
DelLine
Cancella la riga su cui è posizionato il cursore.
InsLine
Inserisce una linea vuota sotto quella su cui è posizionato il
cursore.
GotoXY
Sposta il cursore sulla riga X e colonna Y indicate.
WhereX
Ritorna la posizione della riga su cui si trova il cursore
WhereY
Ritorna la posizione della colonna su cui si trova il cursore
TextBackground
Seleziona il colore dello sfondo
TextColor
Seleziona il colore del testo
LowVideo
I successivi caratteri sono scritti a bassa luminosità.
NormVideo
Ripristina, per il testo, il valore che esso aveva all’inizio del
programma.
HighVideo
I successivi caratteri sono scritti ad alta luminosità.
Window
Apre una finestra di testo.
ReadKey
Legge carattere da tastiera senza visualizzarlo sul video.
KeyPressed
Funzione che ritorna vero se è stato premuto un tasto.
Delay
Attende per il numero di millisecondi indicati.
MODULO GRAPH
InitGraph
DetectGraph
SetGraphMode
GetMaxX;
GetMaxY;
RestoreCRTMode
CloseGraph
ClearViewPort
ClearDevice
Line
LineTo
LineRel
Rectangle
Circle
Arc
Ellipse
MoveTo
ImageSize
PutPixel
GetPixel
GetX
GetY
OutText
OutTextXY
SetColor
SetBkColor
Pone il sistema in modalità grafica.
Rileva il tipo di scheda grafica presente nel computer.
imposta un determinato sistema grafico.
Ritorna il massimo numero di pixel orizzontali del modo grafico
corrente.
Ritorna il massimo numero di pixel verticali del modo grafico
corrente.
Riporta il video al sistema attivo prima dell’inizializzazione della
grafica.
Rende inattivo il sistema grafico.
Cancella la viewport attiva posizionando il puntatore corrente
nell’origine della viewport.
Cancella il video posizionando il puntatore corrente in (0,0).
Disegna una linea dalle coordinate (x1,y1) alle coordinate
(x2,y2).
Disegna una linea dalla posizione attuale del puntatore corrente
alle coordinate (x,y).
Disegna una linea dalla posizione attuale del puntatore corrente
fino alla distanza indicata.
Disegna un rettangolo con spigolo superiore in (x1,y1) e inferiore
in (x2,y2).
Disegna un cerchio con centro in (x,y) e raggio r.
Disegna un arco di cerchio con centro in (x,y) dall’angolo iniziale
all’angolo finale
Disegna un arco di ellisse con centro in (x,y) dall’angolo iniziale
all’angolo finale.
Sposta il puntatore corrente alle coordinate (x,y).
Ritorna numero di byte necessario per memorizzare un’area
dello schermo.
Accende un pixel alle coordinate (x,y).
Riporta il valore del pixel delle coordinate (x,y).
Ritorna la coordinata x del puntatore corrente.
Ritorna la coordinata Y del puntatore corrente.
Visualizza una stringa a partire dalla posizione attuale del
puntatore corrente.
Visualizza una stringa a partire dalle coordinate (x,y).
Imposta il colore del disegno.
Imposta il colore dello sfondo.