|
| Appunti
su Programmazione e linguaggio C
a cura del prof. Nunzio
Brugaletta
|
i
linguaggi di programmazione - il
linguaggio C - struttura di un programma - variabili
ed assegnamenti - costanti
- incrementare una variabile
- pre e post incremento
- immissione ed emissione di dati - istruzione
if - istruzione composte
- l'operatore ? - cicli e istruzione while - cicli e istruzione
for - cicli e istruzione do while
I linguaggi di
programmazione
I linguaggi di programmazione permettono
di scrivere algoritmi interpretabili da un sistema
di elaborazione. Un algoritmo scritto in un linguaggio
di programmazione viene chiamato programma
e il processo di scrittura del programma, a partire
dallalgoritmo, viene chiamato codifica.
I linguaggi di programmazione sono costituiti da un
alfabeto e da un insieme di regole che devono essere
rispettate per scrivere programmi sintatticamente
corretti.
Il linguaggio macchina costituito
da zero ed uno è l'unico che pilota direttamente le
unità fisiche dell'elaboratore in quanto è lunico
comprensibile dallelaboratore stesso. È però
estremamente complicato scrivere programmi in tale
linguaggio naturale per la macchina ma completamente
innaturale per luomo. Per poter permettere
un dialogo più semplice con la macchina sono nati
i linguaggi di programmazione.
Il più vecchio linguaggio
di programmazione è il linguaggio assembly. Il linguaggio
assembly è una rappresentazione simbolica del linguaggio
macchina. La scrittura di programmi è enormemente
semplificata rispetto a quest'ultimo. Per essere eseguito
dall'elaboratore un programma in linguaggio assembly
deve essere tradotto in linguaggio macchina; tale
lavoro è a carico di un programma detto assemblatore.
Questi due tipi di linguaggi, detti anche linguaggi
di basso livello sono propri di ogni macchina.
I linguaggi di alto livello
sono più vicini al linguaggio naturale, sono orientati
ai problemi piuttosto che all'architettura della macchina.
Non fanno riferimento ai registri fisicamente presenti
sulla macchina ma a variabili. Per essere eseguiti
devono essere tradotti in linguaggio macchina, e tale
traduzione viene svolta da un programma detto compilatore.
I linguaggi di alto livello sono
in larga misura indipendenti dalla macchina, possono
essere eseguiti su qualsiasi elaboratore a patto che
esista il corrispondente compilatore che ne permetta
la traduzione.
I linguaggi di alto livello si caratterizzano
per essere orientati a specifiche aree applicative.
Questi linguaggi vengono anche detti della terza generazione.
Per ultimi in ordine di tempo sono
arrivati i linguaggi della quarta generazione, ancora
più spiccatamente rivolti a specifiche aree applicative
e, nell'ambito del loro orientamento, utilizzabili
in modo intuivo dall'utente non esperto. Il più famoso
di questi è SQL (Structured Query Language), che opera
su basi dati relazionali. I linguaggi di IV generazione
sono detti non procedurali poiché l'utente
specifica la funzione che vuole svolgere senza entrare
nel dettaglio di come verrà effettivamente svolta.
inizio
Il
linguaggio C
Nel 1972, presso i Bell Laboratories,
Dennis Ritchie progettava e realizzava la prima versione
del linguaggio C. Ritchie aveva ripreso e sviluppato
molti dei principi e dei costrutti sintattici del
linguaggio BCPL, sviluppato da Martin Richards, e
del linguaggio B, sviluppato da Ken Thompson, l'autore
del sistema operativo Unix. Successivamente gli stessi
Ritchie e Thompson riscrissero in C il codice di Unix.
Il C si distingueva dai suoi predecessori
per il fatto di implementare una vasta gamma di tipi
di dati (carattere, interi, numeri in virgola mobile,
strutture) non originariamente previsti dagli altri
due linguaggi. Da allora ad oggi il C ha subito trasformazioni:
la sua sintassi è stata affinata, soprattutto in conseguenza
della estensione object-oriented (C++). Nel
1983, lIstituto Nazionale Americano per gli
Standard (ANSI) ha costituito un comitato per una
definizione del linguaggio C non ambigua e non dipendente
dalla macchina: il risultato è lo standard ANSI
per il C. A questo standard si farà riferimento in
questi appunti.
inizio
Struttura
di un programma
Iniziamo esaminando il programma
del seguente listato.
#include<stdio.h>
main()
{
printf("abc");
printf("def");
printf("ghi");
printf("lmn");
printf("opqrs");
printf("tuvz");
}
Eseguendolo verrà visualizzata la
stringa delle lettere dellalfabeto italiano:
abcdefghilmnopqrstuvz
Dalla parola main,
seguita da parentesi tonda aperta e chiusa, inizia
l'esecuzione del programma. Il corpo del programma,
che comincia dalla parentesi graffa aperta e finisce
alla parentesi graffa chiusa, è composto da una serie
di istruzioni printf
che verranno eseguite sequenzialmente.
L'istruzione printf
permette la stampa su video di ciò che è racchiuso
tra parentesi tonde e doppi apici. Per esempio
printf("abc");
visualizza
abc
Ogni istruzione deve terminare con un carattere di
punto e virgola.
Per poter utilizzare printf,
come le altre funzioni di entrata/uscita, si deve
inserire all'inizio del testo la linea
#include <stdio.h>
che awerte il compilatore di includere
i riferimenti alla libreria standard di input/output
(stdio sta per standard
input/output).
Il C distingue tra lettere maiuscole
e minuscole; dunque occorre fare attenzione, se si
scrive MAIN() o Main() non si fa riferimento a main().
La struttura del programma C che abbiamo usato nell'esempio
è:
inclusione_librerie
main()
{
istruzione1
istruzione2
istruzione3
........
istruzioneN
}
Il punto e virgola conclude listruzione.
Se si desidera che l'uscita di ogni
istruzione printf
venga prodotta su una linea separata, si deve inserire
\n al termine di ogni
stringa e prima della chiusura dei doppi apici, come
nel seguente Listato.
#include <stdio.h>
main()
{
printf("abc\n");
printf("def\n");
printf("ghi\n");
printf("lmn\n");
printf("opqrs\n");
printf("tuvz\n");
}
Eseguendo il programma si otterrà
la visualizzazione delle seguenti stringhe di caratteri
abc
def
ghi
lmn
opqrs
tuvz
In questo caso la prima stringa (abc)
viene stampata su video a partire dalla posizione
attuale del cursore. Se si vuole cominciare la stampa
delle stringhe da una nuova riga basta inserire \n anche allinizio come in:
printf("\nabc\n");
Qui prima si passa ad una
nuova riga, poi si stampa la stringa specificata
e quindi si posiziona il cursore in una nuova
riga.
In generale è bene tenere presente
che ogni printf stampa
a partire dalla posizione in cui si trovava il cursore
(in generale a destra dellultima stampa). Per
poter modificare tale comportamento è necessario inserire
gli opportuni caratteri di controllo. In effetti la
sequenza \n corrisponde
ad un solo carattere, quello di nuova linea (newline).
Nella printf
possono inserirsi altri caratteri di controllo di
cui si forniscono di seguito quelli che possono avere
utilizzo più frequente:
- \n porta il cursore
allinizio della riga successiva
- \t porta il cursore
al prossimo fermo di tabulazione (ogni fermo di
tabulazione è fissato ad 8 caratteri)
- \a (alert)
fa emettere un suono dallo speaker
- \ stampa
un apice
- \" stampa
le virgolette
inizio
Variabili
e assegnamenti
Supponiamo di voler calcolare l'area
di un rettangolo i cui lati hanno valori interi. Entrano
in gioco due variabili, la base e l'altezza, il cui
prodotto è ancora un valore intero, l'area appunto.
#include <stdio.h>
/*
Calcolo area rettangolo */
main(){
int
base;
int
altezza;
int
area;
base
= 3;
altezza
= 7;
area
= base*altezza;
printf("%d",area);
}
Per rendere evidente la funzione
espletata dal programma si è inserito un commento:
/* Calcolo
area rettangolo */
I commenti possono estendersi su
più linee e apparire in qualsiasi parte del programma,
devono essere preceduti da /*
e seguiti da */, tutto
ciò che appare nelle zone così racchiuse non viene
preso in considerazione dal compilatore e non ha alcuna
influenza sul funzionamento del programma, è però
importantissimo per chi legge il programma: è infatti
nelle righe di commento che viene specificato il senso
delle istruzioni che seguiranno. Cosa, questa, non
immediatamente comprensibile se si leggono semplicemente
le istruzioni del linguaggio.
Subito dopo main()
sono presenti le dichiarazioni delle variabili intere
necessarie:
int base; int
altezza; int area;
La parola chiave int
specifica che l'identificatore che lo segue si riferisce
ad una variabile di tipo intero; dunque base, altezza e area sono variabili di questo tipo.
Anche le dichiarazioni così come
le altre istruzioni devono terminare con un punto
e virgola. Nel nostro esempio alla dichiarazione del
tipo della variabile corrisponde anche la sua definizione
che fa sì che le venga riservato uno spazio in memoria
centrale.
Il nome di una variabile la identifica,
il suo tipo ne definisce la dimensione e l'insieme
delle operazioni che vi si possono effettuare. La
dimensione può variare rispetto all'implementazione;
molte versioni del C, come quelle sotto i sistemi
operativi MS-DOS e Unix, riservano per gli int
uno spazio di due byte, il che permette di poter lavorare
su interi che vanno da -32768 a +32767. Tra le operazioni
permesse fra int vi
sono: la somma (+), la sottrazione (-),
il prodotto (*) e
la divisione (/).
Effettuata la dichiarazione, la variabile
può essere utilizzata. L'istruzione
base
= 3;
assegna alla variabile base il valore
3; cioè inserisce nello spazio di memoria riservato
a tale variabile il valore indicato. Effetto analogo
avrà altezza=7. L'assegnamento è dunque realizzato mediante
l'operatore = .
Nel linguaggio C è possibile assegnare
lo stesso valore a più variabili contemporaneamente.
Per esempio se le dimensioni riguardavano un quadrato,
si sarebbe potuto scrivere:
base
= altezza = 5;
In questo caso prima verrebbe assegnato
il valore 5 alla variabile altezza
e quindi, il risultato dellassegnazione (cioè
5), viene assegnato
alla variabile base.
L'istruzione:
area
= base * altezza;
assegna alla variabile area
il prodotto dei valori di base
e altezza .
L'operatore asterisco effettua l'operazione
di prodotto tra la variabile che lo precede e quella
che lo segue, è dunque un operatore binario.
L'ultima istruzione
printf("%d",area);
visualizza 21,
il valore della variabile area.
Tra i doppi apici, il simbolo di percentuale %
specifica che il carattere che lo segue definisce
il formato di stampa della variabile area;
d (decimale) indica
che si tratta di un intero del quale si desidera la
visualizzazione nel sistema decimale.
Le dichiarazioni delle variabili
dello stesso tipo possono essere scritte in sequenza
separate da una virgola:
int
base,altezza,area;
Dopo la dichiarazione di tipo sono
specificati gli identificatori di variabile, che possono
essere in numero qualsiasi, separati da virgola e
chiusi da un punto e virgola. In generale quindi la
dichiarazione di variabili ha la seguente forma:
tipo lista_di identificatori;
Esistono inoltre delle regole da
rispettare nella costruzione degli identificatori:
devono iniziare con una lettera o con un carattere
di sottolineatura _ e possono contenere lettere, cifre
e _. Per quanto riguarda la lunghezza occorre tenere
presente che soltanto i primi trentadue caratteri
sono significativi, anche se nelle versioni del C
meno recenti questo limite scende a otto caratteri.
Sarebbe comunque opportuno non iniziare il nome della
variabile con il carattere di sottolineatura ed è
bene tenere presente che le lettere accentate, permesse
dalla lingua italiana, non sono considerate lettere
ma segni grafici e le lettere maiuscole sono considerate
diverse dalle rispettive minuscole.
Oltre a rispettare le regole precedentemente
enunciate, un identificatore non può essere una
parola chiave del linguaggio, né può essere
uguale ad un nome di funzione libreria o scritta dal
programmatore.
Allo scopo di rendere più chiaro
l'effetto ottenuto dal programma dell'esempio precedente,
si possono visualizzare i valori delle variabili base
e altezza.
printf("%d
",base);
printf("%d
",altezza);
printf("%d",area);
Nelle prime due printf
si è inserito all'interno dei doppi apici, di seguito
all'indicazione del formato di stampa %d, uno spazio, in modo che venga riportato, in fase
di visualizzazione, dopo il valore della base e dell'altezza,
così da ottenere
3 7 21
e non
3721
È opportuno, per motivi di chiarezza,
far precedere la visualizzazione dei valori da una
descrizione. In questo caso è sufficiente inserirla
tra doppi apici.
printf("Base:
%d ",base);
printf("Altezza:
%d ",altezza);
printf("Area:
%d",area);
Quello che si ottiene in esecuzlone
è
Base:
3 Altezza: 7 Area: 21
Per ottenere una distanza maggiore
tra il valore di base e altezza e le seguenti descrizioni
si possono aggiungere ulteriori spazi
printf("Base:
%d",base);
printf("\tAltezza:
%d",altezza);
printf("\tArea:
%d",area);
così da avere
Base:
3 Altezza: 7 Area: 21
Per far in modo che ad ogni visualizzazione
corrisponda un salto riga si deve inserire \n
prima della chiusura dei doppi apici:
printf("Base:
%d\n",base);
printf("Altezza:
%d\n",altezza);
printf("Area:
%d\n",area);
Si possono effettuare più output
con la stessa istruzione. Per esempio:
printf("Base:
%d Altezza: %d Area: %d",base,altezza,area);
visualizzerebbe:
Base:
3 Altezza: 7 Area: 21
In questo caso figura una lista di
variabili da mandare in output. In sede di esecuzione
ogni simbolo di formato si riferisce ad una variabile
(il primo %d si riferisce a base,
il secondo ad altezza
ecc
). Ovviamente si sarebbero potuti pure inserire
diversi caratteri di formato per formattare, a seconda
delle preferenze, loutput (per es \n
per andare a capo e \t per distanziare).
Osserviamo nel listato il programma
C modificato seguendo alcune delle caratteristiche
introdotte.
#include <stdio.h>
/*
Calcolo area rettangolo */
main(){
int
base,altezza,area;
base
= 3;
altezza
= 7;
area
= base*altezza;
printf("Base:
%d Altezza: %d\n Area: %d",base,altezza,area);
}
L'esecuzione del programma avrà il
seguente effetto:
Base:
3 Altezza: 7
Area:
21
Mentre int
è una parola chiave del C e fa parte integrante del
linguaggio, base,
altezza e area sono
identificatori di variabili scelti a nostra discrezione.
Lo stesso effetto avremmo ottenuto utilizzando al
loro posto altri nomi generici quali x,
y e z
solo che il programma sarebbe risultato meno comprensibile.
La forma grafica data al programma
è del tutto opzionale; una volta rispettata la sequenzialità
e la sintassi, la scrittura del codice è libera. In
particolare più istruzioni possono essere scritte
sulla stessa linea. E indubbio che il programma risulterà
notevolmente meno leggibile del precedente.
Lo stile grafico facilita enormemente
il riconoscimento dei vari pezzi di programma e consente
una diminuzione di tempo nelle modifiche, negli ampliamenti
e nella correzione degli errori. In generale è inoltre
bene dare alle variabili dei nomi significativi, in
modo che, quando si debba intervenire a distanza di
tempo sullo stesso programma, si possa facilmente
ricostruire l'uso che si è fatto di una certa variabile.
inizio
Costanti
Nel programma visto precedentemente
i valori di base e altezza sono
costanti, dato che non variano durante l'esecuzione
del programma. Evidentemente avremmo potuto scrivere
direttamente
area
= 3 * 7;
Quando un certo valore viene utilizzato
in modo ricorrente è opportuno rimpiazzarlo con un
nome simbolico; per farlo dobbiamo definire, all'inizio
del programma, mediante l'istruzione define
un identificatore di costante in corrispondenza del
valore desiderato.
#define BASE
3
Grazie a questa istruzione potremo
utilizzare, all'interno del programma, BASE
al posto del valore intero 3.
La stessa definizione di costante
implica che il suo valore non può essere modificato:
BASE può essere utilizzata
in un'espressione a patto che su di essa non venga
mai effettuato un assegnamento.
Vediamo nel Listato come viene modificato
il programma del paragrafo precedente con l'utilizzazione
delle costanti.
#include <stdio.h>
#define
BASE 3
#define
ALTEZZA 7
/*
Calcolo area rettangolo */
main(){
int
area;
area
= BASE * ALTEZZA;
printf("Base:
%d\n",BASE);
printf("Altezza:
%d\n",ALTEZZA);
printf("Area:
%d\n",area);
}
Il nome di una costante può essere
qualsiasi identificatore valido in C, comunque abbiamo
scelto di utilizzare esclusivamente caratteri maiuscoli
per le costanti e caratteri minuscoli per le variabili
per distinguere chiaramente le une dalle altre. Le
costanti BASE e ALTEZZA
vengono considerate di tipo intero in quanto il loro
valore è costituito da numeri senza componente frazionaria.
Invece di utilizzare direttamente
i valori, è consigliabile far uso degli identificatori
di costante che sono descrittivi e quindi migliorano
la leggibilità dei programmi. Inoltre, se ci si rende
conto che un certo valore utilizzato più volte deve
essere cambiato, nella prima ipotesi, è necessario
ricercalo con attenzione all'interno del testo e modificarlo
dov'è il caso, nella seconda ipotesi è sufficiente
intervenire sulla sua definizione. Per esempio, per
fare in modo che il programma precedente calcoli l'area
del rettangolo con base 102
e altezza 34, è sufficiente
modificare le linee dov'è presente l'istruzione define.
#define
BASE 102
#define
ALTEZZA 34
In sintesi, l'uso delle costanti
migliora due parametri classici di valutazione dei
programmi: flessibilità e possibilità di
manutenzione.
La define
è in realtà una macroistruzione (brevemente, macro)
del precompilatore C che offre altre possibilità
oltre a quella di definire delle costanti.
inizio
Incrementare
una variabile
Ogni nuova assegnazione ad una variabile,
distrugge un valore precedentemente contenuto nella
variabile stessa. Per cui, nel successivo esempio:
...
voto
= 3;
...
voto
= 6;
la variabile voto
varrà 6. E ciò qualunque sia stato il valore precedente.
Per aggiungere uno al valore
contenuto in una variabile si deve assegnare alla
variabile il valore precedente più uno. Ad
esempio, questa istruzione aggiunge uno al contenuto
della variabile n:
n
= n+1;
Difatti il C calcola per prima cosa
il valore dell'espressione posta a destra del segno
di uguale, cioè n+1.
Se ad esempio n vale 5, n+1 vale 6. Questo valore
viene poi assegnato alla variabile indicata a sinistra,
cioè alla stessa n. Quindi n, che prima
valeva 5, dopo l'esecuzione dell'istruzione vale 6.
Questo si chiama incrementare
una variabile, cioè appunto aggiungere un nuovo
valore al valore precedente (nel caso esaminato si
aggiunge 1). L'operazione opposta (togliere, per esempio, 1 al valore della variabile) è chiamata decrementare
la variabile. Ovviamente si può usare lo stesso
sistema per compiere qualunque operazione sul contenuto
della variabile:
area
= area*2; /* raddoppia larea */
segmento
= segmento/k; /* divide il segmento per k */
Il linguaggio C dispone di un operatore
speciale per incrementare una variabile di una unità.
Scrivere:
contakm++;
equivale a scrivere:
contakm
= contakm+1;
Cioè ad incrementare di una unità
il valore della variabile contakm. L'operatore ++
è l'operatore di autoincremento. L'operatore
reciproco -- (due
simboli meno) decrementa di una unità il valore
di una variabile:
altezza--;
/* riduce laltezza di 1 */
L'operatore --
è quindi l'operatore di autodecremento.
Si sono viste, quindi, due tecniche
per aggiungere uno al valore contenuto in una variabile:
|
fogli
= fogli+1;
|
fogli++;
|
Esiste anche una terza tecnica:
fogli += 1;
La combinazione += è un esempio di
operatore di assegnazione. L'istruzione:
km
+= 1;
si può leggere: aggiungi uno al valore
corrente della variabile km. L'operatore += non è limitato ad aggiungere 1 ma somma il valore alla sua destra alla variabile
alla sua sinistra. Ad esempio:
| km
+= 37; |
k1
+= k2; |
a
+= (b/2); |
equivalgono rispettivamente a:
| km
= km+37; |
k1
= k1+k2; |
a
= a+(b/2); |
L'operatore += non è l'unico operatore
di assegnazione, si possono usare tutti gli operatori
aritmetici:
km
-= 6; /* toglie 6 ai km percorsi */
lato
*= 2; /* moltiplica il lato per 2 */
volume
/= 3; /* divide il volume per 3 */
...
Nel seguito di questi appunti si
converrà di utilizzare:
- gli operatori di autoincremento e di autodecremento
tutte le volte che una variabile dovrà essere aggiornata
con lunità
- il doppio operatore (es. +=,
-= ecc
) tutte
le volte che si parlerà di aggiornamento generico
di una variabile (per es. negli accumulatori)
- loperatore di assegnamento generico (cioè
=) in tutti gli
altri casi.
inizio
Pre
e post-incremento
Per aggiungere uno alla variabile
z si può scrivere
in due modi:
cioè mettere l'operatore ++
prima o dopo del nome della variabile.
In generale, le due forme sono equivalenti.
La differenza importa solo quando si scrive una espressione
che contiene z++ o
++z.
Scrivendo z++,
il valore di z viene prima usato poi incrementato:
int
x,z; /* due variabili intere */
z
= 4; /* z vale 4 */
x
= z++; /* anche x vale 4 ma z vale 5 */
Difatti, prima il valore di
z (4) è stato assegnato ad x,
poi il valore di z
è stato incrementato a 5.
Scrivendo ++z,
il valore di z viene prima incrementato e poi usato:
int
x,z; /* due variabili intere */
z
= 4; /* z vale 4 */
x
= ++z; /* ora x vale 5 come z */
Difatti, prima il valore di
z (4) è stato incrementato a 5,
poi il nuovo valore di z
(5) è stato assegnato
ad x.
inizio
Immissione
ed emissione di dati
Il programma scritto non calcola
l'area di un qualsiasi rettangolo ma soltanto di quello
che ha per base 3
e per altezza 7, supponiamo centimetri.
Per esempio, per trovare l'area di
un rettangolo di base 57 e altezza 20 si deve
intervenire sul programma stesso, scrivendo
#define
BASE 57
#define
ALTEZZA 20
Oppure nel caso della versione del
programma dove non si sono utilizzate le costanti
ma le variabili, dovremmo scrivere
base
= 57;
altezza
= 20:
Dopo aver effettuato nuovamente la
compilazione, la successiva esecuzione restituirà
1140, cioè l'area
del rettangolo in centimetri quadri.
Per rendere il programma più generale,
si deve permettere a chi lo sta utilizzando di immettere
i valori della base e dell'altezza; in questo modo
l'algoritmo calcolerà l'area di un qualsiasi rettangolo.
scanf("%d",&base)
L'esecuzione di questa istruzione
fa sì che il sistema attenda l'immissione di un dato
da parte dell'utente.
Analogamente a quello che accadeva
in printf, %d
indica che si tratta di un valore intero in formato
decimale, tale valore verrà poi assegnato alla variabile
base .
Si presti attenzione al fatto che
in una istruzione scanf il simbolo &
(e commerciale, ampersand) deve precedere immediatamente
il nome della variabile; &base sta ad indicare l'indirizzo di memoria in
cui si trova la variabile base.
È infatti noto che le locazioni di memoria in cui
sono conservati i dati, sono distinguibili una dallaltra
mediante un indirizzo. Il nome della variabile è una
etichetta che viene assegnata, per nostra comodità,
ad una o più locazioni di memoria consecutive. L'istruzione
scanf("%d",&base);può allora essere così
interpretata: leggi un dato intero e collocalo
nella posizione di memoria il cui indirizzo è &base
(praticamente lindirizzo corrispondente
alla variabile base).
Durante l'esecuzione di un programma
può essere richiesta all'utente l'immissione di più
informazioni, perciò è opportuno visualizzare delle
frasi esplicative; a tale scopo facciamo precedere
le istruzioni scanf
da appropriate printf.
printf("Valore
base: ");
scanf("%d",
&base);
L'argomento di printf
è semplicemente una costante, quindi deve essere racchiuso
tra doppi apici. Non è necessario neanche richiedere
un salto a linea nuova mediante un \n,
in quanto l'immissione può avvenire sulla stessa riga.
Quello che apparirà all'utente in
fase di esecuzione del programma sarà
Valore
base: _
In questo istante l'istruzione scanf
attende l'immissione di un valore. Se l'utente digita
15 seguito da <Invio>.
Valore
base: 15 <Invio>
questo dato verrà assegnato alla
variabile base
Analogamente possiamo modificare
il programma per l'immissione dell'altezza e magari
aggiungere un'intestazione che spieghi all'utente
cosa fa il programma, come nel listato seguente:
#include <stdio.h>
/*
Calcolo area rettangolo */
main(){
int
base,altezza,area;
printf("Calcolo
AREA RETTANGOLO \n \n");
printf("Valore
base: ");
scanf("%d",&base);
printf("\nValore
altezza: ");
scanf("%d",&altezza);
area
= base*altezza;
printf("\nBase:
%d Altezza: %d\n",base,altezza);
printf("Area:
%d",area);
}
Vediamo l'esecuzione del programma
nell'ipotesi che l'utente inserisca i valori 10 e
13.
Calcolo
AREA RETTANGOLO
Valore
base: 10 <Invio>
Valore
altezza: 13 <Invio>
Base:
10 Altezza: 13
Area:
130
Notare luso del newline
per controllare il modo in cui il programma visualizzerà
i suoi risultati. I due \n
della prima printf,
per esempio, servono: il primo per passare ad una
nuova linea, il secondo per lasciare una linea vuota.
Con una sola istruzione di input
è possibile acquisire più di un valore, per cui i
due input dellesempio precedente, avrebbero
potuto essere sostituiti da:
printf("Introdurre
Base e Altezza separati da una virgola\n");
scanf("%d,%d",&base,&altezza);
In questo caso, quando il programma
viene eseguito, alla richiesta di input si risponderà
con due numeri (che saranno assegnati rispettivamente
a base e ad altezza),
separati da una virgola. Il motivo della presenza
della virgola è dovuto alla specifica presente nella
scanf: infatti ci
sono due %d separati
da una virgola.
inizio
Istruzione
if
Quando si desidera eseguire un'istruzione
al presentarsi di una certa condizione, si utilizza
l'istruzione if.
Per esempio, se si vuole visualizzare
il messaggio "il valore attuale di i è minore di 100" solamente
nel caso in cui il valore della variabile intera i
è minore di 100, si scrive:
if(i<100)
printf("\n il valore attuale di i è minore
di 100");
La sintassi dell'istruzione if è:
if(espressione)
istruzione
dove la valutazione di espressione
controlla l'esecuzione di istruzione:
se espressione è vera viene
eseguita istruzione.
Nell'esempio seguente il programma
richiede un numero all'utente e, se tale numero è
minore di 100, visualizza
un messaggio.
#include
<stdio.h>
/*
Esempio utilizzo if */
main(){
int
i;
scanf("%d",&i);
if
(i<100)
printf("\n
minore di 100");
}
L' espressione i<100
è la condizione logica che controlla l'istruzione
di stampa e pertanto la sua valutazione potrà restituire
soltanto uno dei due valori booleani vero o
falso che in C corrispondono rispettivamente
ai valori interi uno e zero.È appunto
per tale ragione che l'assegnamento a=i<100,
è del tutto lecito. Viene infatti valutata l'espressione
logica i<100, che
restituisce 1 (vero)
se i è minore di 100
e 0 (falso) se i
è maggiore uguale a 100:
il risultato è dunque un numero intero che viene assegnato
alla variabile a.
L'operatore !=
corrisponde a diverso da, per cui l'espressione
a!=0 significa: il
valore di a è diverso
da zero.
Chiedersi se il valore di a
è diverso da zero è lo stesso che chiedersi se il
valore di a è vero,
il che, in C, corrisponde al controllo eseguito per
default (effettuato in mancanza di differenti
indicazioni), per cui avremmo anche potuto scrivere
scanf("%d",&i);
a
= i<100;
if
(a)
printf("\n
minore di 100");
La sintassi completa dell'istruzione
i f è la seguente:
if(espressione)
istruzione1
[else
istruzione2]
dove la valutazione di espressione
controlla l'esecuzione di istruzione1
e istruzione2: se espressione
è vera viene eseguita istruzione1,
se è falsa viene eseguita istruzione2.
Nell'esempio anteriore è stato omesso
il ramo else: il fatto
è del tutto legittimo in quanto esso è opzionale,
come evidenziato dalle parentesi quadre presenti nella
forma sintattica completa.
La tabella seguente mostra gli operatori
utilizzabili nell'istruzione if :
|
Operatore
|
Esempio
|
Risultato
|
|
!
|
!a
|
(NOT logico)
1 se a è 0, altrimenti 0
|
|
<
|
a<b
|
1 se a<b,
altrimenti 0
|
|
<=
|
a<=b
|
1 se a<=b,
altrimenti 0
|
|
>
|
a>b
|
1 se a>b,
altrimenti 0
|
|
>=
|
a>=b
|
1 se a>=b,
altrimenti 0
|
|
==
|
a==b
|
1 se a
è uguale a b, altrimenti 0
|
|
!=
|
a!=b
|
1 se a
non è uguale a b,
altrimenti 0
|
|
&&
|
a&&b
|
(AND logico)
1 se a e b sono veri, altrimenti 0
|
|
||
|
a||b
|
(OR logico)1 se a è vero, (b non è valutato), 1 se b
è vero, altrimenti 0
|
È opportuno notare che, nel linguaggio
C, il confronto delleguaglianza fra i valori
di due variabili viene effettuato utilizzando il doppio
segno ==. Si confrontino
i seguenti due frammenti:
|
Programma A
|
Programma B
|
|
|
|
if
(a==b)
|
If
(a=b)
|
|
printf("Sono
uguali\n");
|
printf("Valore
non zero\n");
|
Il programma A confronta
il contenuto della variabile a ed il contenuto della variabile b:
se sono uguali stampa la frase specificata.
Il programma B assegna ad
a il valore attualmente
contenuto in b e verifica
se è diverso da zero: in tal caso stampa la frase
specificata.
Una ulteriore osservazione va fatta
a proposito degli operatori logici ! (NOT logico), &&
(AND logico) e ||
(OR logico) che vengono usati per mettere assieme
più condizioni. Es.
|
if
(a>5 && a<10)
|
if
(a<2 || a>10)
|
|
Printf("a
compreso fra 5 e 10");
|
printf("a
può essere <2 oppure >10");
|
inizio
Istruzioni
composte
L'istruzione composta, detta anche
blocco, è costituita da un insieme di istruzioni
inserite tra parentesi graffe che il compilatore tratta
come se fosse un'istruzione unica.
Un'istruzione composta può essere
scritta nel programma dovunque possa comparire
un'istruzione semplice. Si noti la differenza di esecuzioni
dei due frammenti di programma seguenti:
|
Programma A
|
Programma B
|
|
|
|
if
(a>100)
|
if
(a>100) {
|
|
printf("Prima
frase \n");
|
printf("Prima
frase \n");
|
|
printf("Seconda
frase \n");
|
printf("Seconda
frase \n");
|
|
};
|
Il programma A visualizzerà
"Prima frase"
solo se a è maggiore
di 100, "Seconda frase" verrà visualizzato in ogni caso:
la sua visualizzazione prescinde infatti dalla
condizione.
Il programma B, qualora a
non risulti maggiore di 100, non visualizzarà alcuna
frase: le due printf
infatti sono raggruppate in un blocco la cui esecuzione
è vincolata dal verificarsi della condizione.
Un blocco può comprendere anche una
sola istruzione. Ciò può essere utile per aumentare
la chiarezza dei programmi: listruzione compresa
in una if può essere opportuno racchiuderla in un blocco anche
se è una sola. In tal modo risulterà più evidente
la dipendenza dellesecuzione della istruzione
dalla condizione.
inizio
loperatore
?
Loperatore "?"
ha la seguente sintassi:
espr1
? espr2 : espr3
Se espr1
è vera restituisce espr2 altrimenti restituisce espr3.
Si può utilizzare tale operatore
per assegnare, condizionatamente, un valore ad una
variabile. In questo modo può rendere un frammento
di programma meno dispersivo:
|
Programma A
|
Programma B
|
|
|
|
if
(a>100)
|
sconto=(a>100
? 10 : 5);
|
|
sconto=10;
|
|
|
else
|
|
|
sconto=5;
|
|
inizio
Cicli
e istruzione while
Le strutture cicliche assumono nella
scrittura dei programmi un ruolo fondamentale, non
fosse altro per il fatto che, utilizzando tali strutture,
si può istruire leleboratore affinché esegua
azioni ripetitive su insiemi di dati diversi: il che
è, tutto sommato, il ruolo fondamentale dei sistemi
di elaborazione.
È in ragione delle suddette considerazioni
che i linguaggi di programmazione mettono a disposizione
del programmatore vari tipi di cicli in modo da adattarsi
più facilmente alle varie esigenze di scrittura dei
programmi. La prima struttura che prendiamo in considerazione
è il ciclo while (ciclo
iterativo con controllo in testa):
while(esp)
istruzione
Viene verificato che esp
sia vera, nel qual caso viene eseguita istruzione.
Il ciclo si ripete fintantoché esp
risulta essere vera.
Naturalmente, per quanto osservato prima, istruzione
può essere un blocco e, anche in questo caso, può
essere utile racchiudere listruzione in un blocco
anche se è una sola.
Scriviamo, a titolo di esempio di
uso del ciclo while, un frammento di programma che calcola la somma
di una serie di valori positivi immessi dall'utente:
...
somma = 0;
printf("\n
Inserisci un intero positivo:");
scanf("%d",
&numero);
while(numero)
{
somma += numero;
printf("\n
Inserisci un intero positivo:");
scanf("%d",
&numero);
}
In questo caso il controllo allinizio
del ciclo garantisce la fine della elaborazione non
appena la variabile numero
assume valore zero: il ciclo viene ripetuto mentre
numero è diverso da
zero. Linput, fuori ciclo, del primo numero
da elaborare permette di impostare la condizione di
controllo sul ciclo stesso. Il totalizzatore somma cumula tutti i valori provenienti da input.
inizio
Cicli
e istruzione for
Listruzione for
viene utilizzata tradizionalmente per codificare cicli
a contatore: istruzioni cicliche cioè che devono essere
ripetute un numero definito di volte.
Il formato del costrutto for
è il seguente:
for(esp1; esp2; esp3)
istruzione
Si faccia attenzione ai punti e virgola
posti tra parentesi. Il ciclo inizia con l'esecuzione
di esp1 (inizializzazione
del ciclo) la quale non verrà più eseguita. Quindi
viene esaminata esp2 (condizione
di controllo del ciclo). Se esp2
risulta vera, viene eseguita istruzione, altrimenti
il ciclo non viene percorso neppure una volta. Successivamente
viene eseguita esp3 (aggiornamento)
e di nuovo valutata esp2
che se risulta essere vera dà luogo ad una nuova esecuzione
di istruzione. Il processo si ripete finché esp3
risulta essere falsa.
Se supponiamo di voler ottenere la
somma di tre numeri interi immessi dall'utente, si
può scrivere:
...
somma = 0;
for(i = 1;
i <= 3; i++) {
scanf("%d",
&numero);
somma += numero;
}
Il programma per prima cosa assegna
il valore 1 alla variabile
i (la prima espressione
del for), si controlla se il valore di i
è non superiore a 3
(la seconda espressione) e poiché lespressione
risulta vera verranno eseguite le istruzioni inserite
nel ciclo (linput di numero
e laggiornamento di somma). Terminate le istruzioni che compongono il ciclo
si esegue laggiornamento di i
così come risulta dalla terza espressione contenuta
nel for, si ripete
il controllo contenuto nella seconda espressione e
si continua come prima finché il valore di i
non rende falsa la condizione.
Questo modo di agire del ciclo for
è quello comune a tutti i cicli di questo tipo messi
a disposizione dai compilatori di diversi linguaggi
di programmazione. Il linguaggio C mette a disposizione
delle opzioni che espandono abbondantemente le potenzialità
del for generalizzandolo
in maniera tale da comprendere, per esempio, come
caso particolare il ciclo while.
Il frammento di programma per la somma di una serie
di numeri positivi, scritto in precedenza, potrebbe,
per esempio, essere riscritto:
...
printf("\n
Inserisci un intero positivo:");
scanf("%d",
&numero);
for(somma=0;numero;)
{
somma += numero;
printf("\n
Inserisci un intero positivo:");
scanf("%d",
&numero);
}
Il ciclo esegue lazzeramento
di somma (che verrà
eseguito una sola volta) e subito dopo il controllo
se il valore di numero è diverso da zero e, in questo caso, verranno
eseguite le istruzioni del ciclo. Terminate le istruzioni,
poiché manca la terza espressione del for, viene ripetuto il controllo su numero.
Linizializzazione di somma
avrebbe potuto essere svolta fuori dalla for:
in tal caso sarebbe mancata anche la prima espressione.
Poiché, nel linguaggio C, ogni ciclo
while può essere codificato
utilizzando un ciclo for
e viceversa, è bene tenere presente che la scelta
del tipo di codifica da effettuare va sempre fatta
in modo da ottenere la massima chiarezza e
leggibilità del programma.
inizio
Cicli
e istruzione do-while |