• Non ci sono risultati.

Sottoprogrammi in C

N/A
N/A
Protected

Academic year: 2021

Condividi "Sottoprogrammi in C"

Copied!
12
0
0

Testo completo

(1)

1

Sottoprogrammi in C

• I sottoprogrammi sono blocchi di codice C indipendenti da altri moduli, ma non eseguibili singolarmente, ciascuno destinato ad una precisa operazione.

• La comunicazione tra i diversi sottoprogrammi avviene mediante le chiamate, i parametri, i valori di ritorno.

Ricordiamo che:

• I sottoprogrammi consentono di scomporre programmi (problemi) complessi in sottoprogrammi più semplici racchiusi in moduli sfruttabili singolarmente

• L’uso dei sottoprogrammi consente di nascondere l’implementazione di una certa operazione e concentrarsi solo sul “cosa fa” e non sul

“come lo fa” ciascun modulo.

Sottoprogrammi in C

• Una sottoprogramma può:

– compiere un azione (ovvero è una procedura)

– rappresentare una informazione (ovvero è una funzione)

• Nel primo caso la sua invocazione provoca il verificarsi di una certa azione, nel secondo il risultato dell’elaborazione effettuata viene restituito dalla funzione stessa.

(2)

3

Sottoprogrammi in C

• Un sottoprogramma in C viene definito nel seguente modo:

<tipo> nome_sottoprogramma ([<lista parametri formali>])

{ sezione dichiarativa

corpo del sottoprogramma [return <espressione>;]

}

• Un sottoprogramma può avere o meno una lista di argomenti

• Ogni funzione presenta un valore di ritorno che può essere di qualsiasi tipo predefinito o definito dall’utente.

• Se nella dichiarazione viene omesso il tipo ritornato, esso viene considerato automaticamente un intero.

Procedure in C

• In C non esistono le procedure

• Nel caso di un sottoprogramma che compie una azione, ovvero di una procedura, esso è definito come una funzione ma si usa il tipo predefinito void come valore di ritorno; non è ritornato alcun valore.

Funzioni in C

(3)

5

Controllo dell’esecuzione

• All’atto della chiamata di una funzione, il controllo

dell’esecuzione viene passato alla prima istruzione del corpo della funzione stessa.

• Esistono due modi per restituire il controllo al programma chiamante:

– attraverso l’istruzione: return [<espressione>];

– termine dell’esecuzione della funzione “}”

• E’ opportuno controllare sempre che la chiamata di una funzione ed il suo valore di ritorno siano consistenti.

Lista dei parametri formali

• La lista dei parametri è usata per passare dati ad una funzione chiamata. La lista può essere anche vuota.

• I parametri devono essere specificati tra parentesi e separati da virgole, dopo il nome della funzione.

• I parametri devono essere dichiarati con il loro tipo corrispondente.

• Esempio:

float Calcola ( int x, int y , int z) {

<parte dichiarativa>

<corpo della funzione >

[return <espressione>;]

}

(4)

7

Esempio

#include <stdio.h>

// funzione che calcola il cubo di una variabile int cube(int x)

{

int a=x*x*x;

return a;

} main () {

int I;

printf("Immetti numero per calcolarne il cubo ”);

scanf(“%d”, &I);

printf("Cubo = %d \n”, cube(I));

}

Parametri di una funzione

• Il metodo di passaggio dei parametri è, per default, per valore, (la funzione chiamata opererà su una copia locale dei parametri attuali passati e non ne modifica il loro valore globale

• è possibile passare i parametri per “riferimento”, utilizzando puntatori

• E’ responsabilità del programmatore controllare che il numero ed il tipo degli argomenti passati ad una funzione corrisponda con quanto specificato nella dichiarazione della funzione stessa.

N.B. parametri di tipo array sono passati sempre per riferimento

(5)

9

Prototipo di una funzione

Il prototipo di una funzione rappresenta una dichiarazione di funzione (indicandone la sola intestazione) antecedente alla sua definizione.

Es. : int function(int x, char c); int function(int,char);

L’uso dei prototipi è obbligatorio quando la definzione di una funzione avviene successivamente al suo utilizzo.

Lo scopo dei prototipi delle funzioni è quello di permettere al compilatore di compiere il controllo sui tipi degli argomenti che vengono passati ad una funzione.

Esempio

#include <stdio.h>

int cube(int x); //PROTOTIPO della funzione main ()

{ int I;

printf(" Immetti numero per calcolarne il cubo ”);

scanf(“%d”, &I);

printf("Cubo = %d \n”, cube(I));

}

int cube(int x) {

int a=x*x*x;

return a;

(6)

11

Prototipi di funzione

• Se i prototipi vengono inseriti prima della definizione di una funzione, quando il compilatore incontra la dichiarazione conosce il numero ed i tipi degli argomenti e può controllarli.

• La dichiarazione e la definizione di una funzione devono essere consistenti sia nel numero che nel tipo dei parametri.

• Attenzione se prototipo e definizione di funzione si trovano nello stesso file sorgente eventuali non corrispondenze nei tipi degli argomenti saranno rilevati dal compilatore, in caso contrario al più ci sarà un warning.

• I sottoprogrammi possono essere inseriti in file sorgenti separati dal main; i file sorgenti possono essere compilati separatamente

• nel main, o nei sottoprogrammi che ne chiamano altri in file diversi, dovrà essere indicato che deve essere incluso il file sorgente contenenti i sottoprogrammi chiamati (direttiva #include).

Sottoprogrammi in file separati

#include <stdio.h>

#include </cygdrive/c/cube.h> /*include il file cube.h contenente la funzione cube*/

main () {

int I;

printf("Immetti numero per calcolarne il cubo ”);

scanf(“%d”, &I);

printf("Cubo = %d \n”, cube(I));

}

int cube(int x) {

int a=x*x*x;

return a;

}

La funzione cube è nel file sorgente cube.h Attenzione: i file inclusi vanno memorizzati nella libreria dei file di inclusione altrimenti va indicato per intero il path di memorizzazione

(7)

13

Sottoprogrammi in file separati

#include <stdio.h>

#include </cygdrive/c/leggivet.h>

#include </cygdrive/c/stampavet.h>

main ()

{ const card=5;

int Vet[card],I;

leggivet(Vet,card);

stampavet(Vet,card);

}

… per leggere e stampare i valori di array di interi

…il Programma principale

Sottoprogrammi in file separati

#include <stdio.h>

void leggivet(int Vet1[],int card1) {int I;

for (I=0;(I< card1); I++)

{printf("immetti Vet[ %d ]= \n”,I) ; scanf(“%d”, &Vet1[I]);

} }

#include <stdio.h>

void stampavet(int Vet1[],int card1) { int I;

for (I=0;I<card1; I++)

printf("Vet1[ %d ]= %d \n”, I, Vet1[I] );

Leggivet e stampavet sono due procedure

Quando un parametro formale è un array questo viene passato

automaticamente per riferimento

… i due sottoprogrammi ...

(8)

15

Puntatori

• Un puntatore è una variabile che contiene l’indirizzo di un’altra variabile.

• I puntatori sono “type bound” cioè ad ogni puntatore è associato il tipo a cui il puntatore si riferisce.

• Nella dichiarazione di un puntatore bisogna specificare un asterisco (*) davanti al nome della variabile pointer.

• Esempio:

– int *pointer; // puntatore a intero – char *pun_car; // puntatore a carattere – float *flt_pnt; // puntatore a float

Inizializzazione di puntatori

• Prima di poter usare un puntatore questo deve essere inizializzato, assegnandogli l’indirizzo di una variabile

• L’operatore unario & fornisce l’indirizzo di una variabile Es.:

int volume, *vol_ptr; // dichiara il puntatore a *vol_ptr

vol_ptr = &volume; // assegna a *vol_ptr l’indirizzo di volume

Il puntatore vol_ptr contiene ora l’indirizzo della variabile volume.

• Per assegnare un valore all’oggetto puntato da vol_ptr occorre utilizzare l’operatore di indirezione “ * “.

*vol_ptr= 15;

(9)

17

Inizializzazione di puntatori

int volume, *vol_ptr; // dichiara il puntatore a *vol_ptr

vol_ptr = &volume; // assegna a *vol_ptr l’indirizzo di volume

*vol_ptr= 15;

Locazione di memoria assegnata a volume

Locazione di memoria assegnata a vol_ptr

vol_ptr = &volume; ==> vol_ptr = 3221

*vol_ptr= 15; ==> volume = 15

3221

4345

. . .

3221 15

Indirizzi memoria

Memoria

Puntatori come argomenti di funzioni

• Se un parametro formale di una funzione è una variabile puntatore il meccanismo di scambio dei parametri

avviene per riferimento (per indirizzo) ossia la funzione chiamata sarà in grado di modificare il valore del

parametro effettivo che riceve.

• Passaggio argomenti per valore:

int numero;

square(numero); //chiamata della funzione square

• Passaggio per indirizzo:

square(&numero); //chiamata della funzione square

(10)

19

Esempio

#include <stdio.h>

void swap(int x, int y) {

int temp;

temp = x;

x = y;

y = temp;

}

main() {

int a = 3;

int b = 5;

swap(a,b);

printf(“a= %d b= %d\n”,a,b);

}

Qual’è l’output del programma ? a=3 b=5

Questo accade perché la funzione swap agisce solo su una copia delle variabili a e b (i parametri x e y sono passati per valore)

Per far sì che la funzione agisca sulle variabili stesse e non su delle copie occorre passare gli indirizzi delle variabili.

Esempio

#include <stdio.h>

void swap(int *x_ptr, int *y_ptr) {

int temp;

temp = *x_ptr;

*x_ptr = *y_ptr;

*y_ptr = temp;

} main() {

int a = 3;

int b = 5;

swap(&a,&b);

printf(“a= %d b= %d\n”,a,b);

}

Qual’è l’output del programma ? a=5 b=3

Ora x e y sono parametri formali passati per

rifrgimento

(11)

21

Esempio

/* Conta i caratteri numerici in una stringa */

main() {

char linea[80];

int numero;

printf(“Inserisci una linea di testo\n”);

LeggiLinea(linea,80);

ContaDigit(linea,&numero);

printf(“La linea %s contiene %d numerici”, linea, numero);

}

Esempio

/*Legge una linea in input */

void LeggiLinea(char ln[] , int max) {

int c, i = 0;

while ( (c=getchar())!='\n' && i < max) {ln[i] = c;

i++;

} ln[i] = '\0';

}

(12)

23

Esempio

/*Conta il numero di cifre numeriche */

void ContaDigit(char ln2[], int *times) {int i;

*times = 0;

for(i=0 ; ln2[i] != '\0' ;i++)

if ((ln2[i] >= '0') && (ln2[i] <= '9')) (*times)++;

}

Riferimenti

Documenti correlati

[r]

[r]

[r]

[r]

Se la cartella da aprire è presente nella lista di cartelle della finestra di dialogo Apri che si apre sullo schermo, selezionarla con il mouse e fare clic sul pulsante

■ Quindi il vero argomento della prima funzione non é la seconda funzione, ma un normale valore, che può avere qualsiasi origine (variabile, espressione ecc...), e in particolare

________________; l’ausiliare dei verbi intransitivi è, in genere, essere. Sul quaderno scrivi due frasi con ciascuno dei verbi dati, usandoli la prima volta transitivamente e

E responsabilità del programmatore controllare che il numero ed il tipo degli argomenti passati ad una funzione corrisponda con quanto specificato nella dichiarazione della