Introduzione al linguaggio C Dr. Francesco Fabozzi Corso di Informatica.

Post on 01-May-2015

225 views 2 download

transcript

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 */