Introduzione al linguaggio C Dr. Francesco Fabozzi Corso di Informatica.
-
Upload
macario-orlando -
Category
Documents
-
view
226 -
download
2
Transcript of Introduzione al linguaggio C Dr. Francesco Fabozzi Corso di Informatica.
Introduzione al
linguaggio CDr. Francesco Fabozzi
Corso di Informatica
2
Area del cerchio• Programma che calcola l’area di un cerchio
dato il raggio in input
#include <stdio.h>
main(){ float raggio, area; const float pi = 3.141592; printf(“Inserisci il raggio \n”); scanf(“%f”,&raggio); area = raggio*raggio*pi; printf(“area del cerchio = %f \n”, area); }
3
Funzione area del cerchio• Modifichiamo il programma incapsulando il
calcolo dell’area in una funzione#include <stdio.h>float AreaCerchio(float r);main(){ float raggio; printf(“Inserisci il raggio \n”); scanf(“%f”,&raggio); printf(“area del cerchio = %f \n”, AreaCerchio(raggio) );}float AreaCerchio( float r ){ float area; const float pi = 3.141592; area = r * r * pi; return area;}
Dichiarazione o prototipo della funzione
Definizione della funzione
4
Funzioni in C• Una funzione in C può essere chiamata in
qualsiasi parte di un programma
• Una funzione può accettare una lista di parametri in input (argomenti passati alla funzione) e può restituire un valore in output
• Una funzione può essere definita o nello stesso file sorgente del main o in un altro file sorgente
5
Definizione di una funzione• La definizione di una funzione deve
specificare il suo nome, il tipo restituito, i tipi dei parametri e i loro nomi
• I nomi dei parametri sono locali alla funzione stessa e non sono visibili a nessun’altra funzione– Possono quindi essere usati da altre funzioni
senza conflitti
tipo_restituito nome_funzione(lista parametri){…}
6
Chiamata “per valore”• In C gli argomenti di una funzione sono
passati “per valore” (by value)– Gli argomenti passati alla funzione non sono
accessibili direttamente da questa ma sono copiati in variabili temporanee locali alla funzione
• La funzione opera sulle variabili temporanee
• Una chiamata di funzione non può modificare una variabile della funzione chiamante
7
Chiamata “per valore”• Esempio:
/* elevamento a potenza intera di un intero */int potenza( int base, int n ){ for( int p = 1; n > 0; n-- ) p *= base; return p;}
La chiamata della funzione potenza non altera il valore di n nella funzione chiamante
8
Parametri formali e reali• Parametri formali
– I parametri usati nella funzione– Sono locali alla funzione stessa
• Parametri reali (actual parameters) – Le variabili della funzione chiamante passate
alla funzione come parametri – Non possono essere alterate dalla funzione
stessa
9
Valore restituito• L’istruzione return serve a restituire il
valore di una qualsiasi espressione alla funzione chiamante– return espressione;
• Se una funzione non restituisce alcun valore il suo tipo è void e l’istruzione return non è accompagnata da nessuna espressione– Il return passa semplicemente il controllo alla
funzione chiamante
10
Valore restituito• Anche la funzione main può restituire un
valore– In genere si fa restituire un intero
• int main( ){ … }
– In genere si fa ritornare 0 se il programma termina correttamente
• return 0;
11
Dichiarazione di una funzione• Prima del main occorre dichiarare le
funzioni che saranno usate
• Nella dichiarazione i nomi dei parametri sono opzionali– float AreaCerchio( float );
• La dichiarazione (o prototipo) di una funzione deve essere in accordo con la sua definizione
12
Funzione area del cerchio• Modifichiamo ancora la funzione inserendo
un controllo sul valore del raggio
float AreaCerchio( float r ){ float area; const float pi = 3.141592; if( r < 0 ) { printf(“raggio non valido!”) area = -1.0; } else area = r * r * pi; return area;}
13
Area di più cerchi• Modifichiamo il programma in modo da
poter calcolare l’area di n cerchi#include <stdio.h>float AreaCerchio(float r);main(){ float raggio; int ncerchi; printf(“Inserisci il numero di cerchi \n”); scanf(“%d”,&ncerchi); for(int i=0; i<ncerchi; i++) { printf(“Inserisci il raggio del cerchio n. %d \n”, i+1); scanf(“%f”,&raggio); printf( “area = %f \n”, AreaCerchio(raggio) ); }}
14
Area di più cerchi• Modifichiamo il programma in modo da poter
calcolare l’area di un numero indefinito di cerchi#include <stdio.h>float AreaCerchio(float r);main(){ float raggio; printf(“Inserisci 0 per terminare \n”); printf(“Inserisci il raggio \n”); scanf(“%f”,&raggio); while( raggio != 0 ) { printf(“area = %f \n”, AreaCerchio(raggio)); printf(“Inserisci il raggio \n”); scanf(“%f”,&raggio); }}
15
Area di più cerchi• Oppure…
#include <stdio.h>float AreaCerchio(float r);main(){ float raggio; int ncerchi; printf(“Inserisci 0 per terminare \n”); do{ printf(“Inserisci il raggio \n”); scanf(“%f”,&raggio); printf(“area = %f \n”, AreaCerchio(raggio)); } while( raggio != 0)}
16
Vettori (arrays)• Un vettore (array) è un gruppo di locazioni
di memoria identificato con un solo nome
• Da un punto di vista logico un vettore è una sequenza di N variabili omogenee (cioè dello stesso tipo)– A[ 0 ], A[ 1 ], …, A[ N-1 ]– A = nome del vettore– N = lunghezza o dimensione del vettore
17
Vettori (arrays)• La lunghezza di un vettore va specificata nella
dichiarazione della variabile oltre al suo tipo e nome
• Un array può essere inizializzato in fase di dichiarazione– In questo caso è opzionale specificarne la lunghezza
• Esempi:– int A[5] : vettore di 5 elementi interi– float raggi[100] : vettore di 100 elementi reali– float s[3]={1.3,2.1,3.4} : vettore di 3
elementi reali– float s[]={1.3,2.1,3.4}
18
Elementi di un array• Un elemento di un array è identificato dal
nome del vettore seguito da un indice intero tra parentesi– Esempi: A[4], raggi[56]– L’indice parte da 0 e non può essere maggiore
della lunghezza del vettore - 1
• L’indice può essere specificato con una variabile, una costante o una generica espressione intera– Esempio: X[n-m]
19
Elementi di un array• Rappresentazione di un vettore• int A[5]
A[ 0 ] 34A[ 1 ] 243A[ 2 ] 3A[ 3 ] 5670A[ 4 ] 761
Locazioni di memoria
Il simbolo A indica anche l’indirizzo della prima locazione di memoria del vettore
20
Vettori come parametri di funzioni• Un vettore può essere passato come
argomento a una funzione
• Per specificare che un parametro formale in una funzione deve essere un vettore occorre far seguire il nome da parentesi quadre– float leggiElemento( float v[ ], int n );– In questo caso non occorre specificare la
dimensione del vettore in quanto essa è definita nella funzione chiamante
21
Vettori come parametri di funzioni• Nel caso dei vettori non si ha la chiamata
“per valore”– Non viene fatta la copia temporanea del
vettore
• Il valore passato alla funzione è l’indirizzo (o puntatore) della prima locazione del vettore
• Una funzione può quindi usare e modificare qualsiasi elemento del vettore che le è stato passato
22
Uso dei vettori• L’uso dei vettori è particolarmente efficace
quando dobbiamo ripetere la stessa operazione su un gruppo di variabili omogenee– In questo caso si può definire un vettore e
iterare sul suo indice
• Altro uso dei vettori è quello di immagazzinare degli elementi per poterli poi ordinare o fare ricerche su di essi
23
Uso dei vettori• Esempio:void sommaVettori(float a[],float b[],float s[],int n){ for(int i = 0; i < n; i++) s[i] = a[i] + b[i]; return;}
void copiaVettori(float a[],float b[],int n){ for(int i = 0; i < n; i++) b[i] = a[i]; return;}
Il vettore passato alla funzione viene modificato dalla chiamata di funzione
24
Uso dei vettori• Esempio:
int cercaElemento(float x,float a[],int n){ int trovato = 0; for(int i = 0; i < n; i++){ if(a[i] == x){ trovato = 1; return trovato; } /* se a[i] != x allora passo all’iterazione successiva */
} /* fine ciclo for */ return trovato;}
25
Array multidimensionali• E’ possibile definire vettori
multidimensionali– Un elemento è identificato da più indici– Esempio: la dichiarazione int c[2] [2];
• Dichiara un vettore con 4 = 2x2 elementi interi• c[0] [0], c[1] [0], c[0] [1], c[1] [1]
– Esempio: dichiarazione e assegnazione• int c[ ] [ ] = { {7,12}, {2,16} };
c[0,0]
c[1,0]
c[0,1]
c[1,1]
26
Puntatori• Una variabile è caratterizzata da un nome,
un tipo e occupa un certo numero di locazioni di memoria a seconda del tipo
indirizzo contenuto
… …100
…
…1000
a
x
5
5
int a = 5;int x;x = a
27
Puntatori• Una puntatore è una variabile che contiene
l’indirizzo della locazione di memoria di un’altra variabile
• Per dichiarare un puntatore occorre specificare il tipo della variabile di cui deve contenere l’indirizzo seguito da uno *
int * Punt_a;Punt_a è un puntatore a una variabile intera
28
Puntatori• Un puntatore quando viene dichiarato non
punta a un indirizzo valido, quindi prima di poterlo usare occorre necessariamente inizializzarlo– Si puó inizializzare a NULL (indica un
puntatore nullo)
int * Punt_a = NULL; Punt_a viene inizializzatoa un puntatore nullo
Puntatore nullo
int * Punt_a;*Punt_a = 100;
ERRORE!
29
L’operatore &• Per assegnare l’indirizzo di una variabile a
un puntatore si fa uso dell’operatore unario & (operatore di referenza)
• L’operatore & restituisce l’indirizzo di una variabile
int a = 5;int * Punt_a;Punt_a = &a;
Punt_a è un puntatore a una variabile intera a cui viene assegnatol’indirizzo della variabile a
Si dice che: Punt_a “punta” ad a
30
L’operatore &
int a = 5;int * Punt_a;Punt_a = &a;
Punt_a “punta” ad a
indirizzo contenuto
… …700000
…
…800000
a
Punt_a
5
700000
31
L’operatore &
int a = 5;int b = 6;printf(“Valore di a = %d \n”, a);/* stampa 5 */printf(“Indirizzo di a = %X \n”, &a);/* stampa l’indirizzo di a */
a = b;printf(“Valore di a = %d \n”, a);/* stampa 6 */printf(“Indirizzo di a = %X \n”, &a);/* stampa l’indirizzo di a (invariato) */
Inserisce un numeroin esadecimale
32
L’operatore *• L’operatore * (operatore di dereferenza)
applicato a un puntatore restituisce il contenuto della locazione a cui il puntatore punta
int a = 5;int b = 6;int c = 7;int * Punt_a = &a;int * Punt_b = &b;c = *Punt_a; /* adesso c = 5 */*Punt_b = a;/* adesso b = 5 */
33
L’operatore *int a = 5;int b = 6;int * Punt_a = &a;printf(“Valore di a = %d \n”, *Punt_a);/* stampa: Valore di a = 5 */printf(“Indirizzo di a = %X \n”, Punt_a);/* stampa l’indirizzo di a */
*Punt_a = b;printf(“Valore di a = %d \n”, a);/* stampa: Valore di a = 6 */
Punt_a = &b;printf(“Indirizzo di a = %X \n”, &a);/* stampa l’indirizzo di a */printf(“Indirizzo di b = %X \n”, Punt_a);/* stavolta stampa l’indirizzo di b */
34
Puntatori void• I puntatori void sono puntatori generici in
cui non viene specificato il tipo di dato
• A un puntatore void può essere assegnato l’indirizzo di qualsiasi tipo di datoint m = 1;float x = 4.35;void * pv;int * pa;pv = &m;/* pv punta a una variabile intera */ pa = (int *) pv;/* per assegnare a pa l’indirizzo a cui punta pv occorre fare un cast */pv = &x;/* pv ora punta a una variabile float */
35
Puntatori const• Un puntatore definito con l’attributo const
non può modificare il contenuto della variabile a cui punta
const int * pa;int m = 1;pa = &m;*pa = 2;/* errore! pa è un puntatore const */
36
Avvertenze sui puntatori• Non confondere puntatore con variabile
puntata– Un puntatore contiene un indirizzo di memoria– La variabile puntata è un’area della memoria
che comincia con l’indirizzo contenuto nel puntatore
• Questa area di memoria dipende dal tipo della variabile
• Un puntatore è anch’esso una variabile– Occupa uno spazio di memoria
• L’area di memoria occupata dal puntatore è quella necessaria per contenere l’indirizzo del dato puntato
37
Puntatori come argomenti di funzioni• Un puntatore può essere passato a una
funzione come suo argomento– E’ il puntatore ad essere copiato come
variabile locale nella funzione– Tramite il puntatore la funzione ha accesso
alla variabile originaria– La funzione può modificare il valore della
variabile di cui è stato passato il puntatore
• In questo caso si dice che la variabile è passata per riferimento (by reference)– Se non si vuole modificare il valore della
variabile occorre passare un puntatore const
38
Puntatori come argomenti di funzioni• Esempio: funzione che ritorna il quadrato di
un intero
int quad1( int n ) { n = n * n; return n;}
int quad2( int * pn ) { *pn = (*pn) * (*pn); return (*pn);}
int i = 3;int m = quad1( i );/* m = 9, i = 3 */
int i = 3;int * pi = &i;int m = quad2( pi );/* m = 9, i = 9 */
Viene passata la variabile Viene passato il puntatore
39
Puntatori come argomenti di funzioni• Esempio: funzione che immagazzina il
prodotto scalare di due vettori in un’altra variabile
void prodScalare( int dim, float a[], float b[], float * val) { *val = 0; for( int i = 0; i < dim; i++ ) *val = *val + a[i] * b[i]; return;}
40
Vettori e puntatori• Il nome di un array è un puntatore alla
prima locazione di memoria dell’array
• L’accesso agli elementi dell’array può essere effettuato anche tramite puntatori
Indirizzo valore Puntatore valore
& A[ 0 ] A[ 0 ] A *A
& A[ 1 ] A[ 1 ] A+1 *(A+1)
& A[ 2 ] A[ 2 ] A+2 *(A+2)
& A[ 3 ] A[ 3 ] A+3 *(A+3)
Elementi di un array
41
Vettori e puntatori• C’è una differenza fondamentale tra il
nome di un array e un puntatore– Un puntatore può cambiare il suo valore– Il nome di un array punta sempre al primo
elemento dell’array e non può cambiare il suo valore
42
Vettori e puntatori• Esempio:
int * pa; int m = 3;int a[5] = {10,21,2,75,9};pa = a;/* pa punta al primo elemento dell’array */*(pa+2) = m;/* adesso a[2]=3 pa = &m;/* OK! adesso pa punta alla variabile m */a = &m/* errore! a non può puntare a un’altra variabile */
43
Stringhe• Una stringa è un vettore di caratteri
terminato dal carattere speciale \0 (carattere di fine stringa o terminatore della stringa)
/ stringa di 14 caratteri */char frase[] = “Il colore blu”; /* oppure */char * frase = “Il colore blu”;
I l c o l o r e b l u \0
\0 = carattere di fine stringa
44
Stringhe• Una stringa può essere assegnata a un
vettore con la funzione scanf()
char parola[20];scanf(“%s”, parola);
NOTA: nella chiamata della funzione scanfparola non è preceduto da &
45
Manipolazione di stringhe• La libreria standard del C fornisce delle
funzioni per la manipolazione di stringhe
#include <string.h>char * strcopy(char* s1, const char * s2)/* copia s2 in s1 e ritorna s1 */
char * strncopy(char* s1, const char * s2, size_t n)/* copia i primi n caratteri di s2 in s1 e ritorna s1 */
char * strcat(char* s1, const char * s2)/* accoda s2 ad s1 e ritorna s1
char * strncat(char* s1, const char * s2, size_t n)/* accoda i primi n caratteri di s2 in s1 e ritorna s1 */
46
Manipolazione di stringhe• La libreria standard del C fornisce delle
funzioni per la manipolazione di stringhe
#include <string.h>int strcmp(const char* s1, const char * s2)/* confronta s1 con s2 e ritorna il risultato: <0 se s1<s2 =0 se s1=s2 >0 se s1>s2*/
size_t * strlen(const char * s)/* ritorna la lunghezza di s */