• Non ci sono risultati.

Sottoprogrammi in C

N/A
N/A
Protected

Academic year: 2021

Condividi "Sottoprogrammi in C "

Copied!
16
0
0

Testo completo

(1)

Elementi di Informatica 1 Prof. G. A. Di Lucca - Univ. del Sannio

Sottoprogrammi in C

• Un sottoprogramma in C viene definito nel seguente modo:

Esempio:

float Calcola ([<lista parametri formali>]) { <parte dichiarativa>

<corpo del sottoprogramma>

[return <espressione>;]

}

Un sottoprogramma può avere o meno una lista di argomenti (parametri)

<tipo> <nome_sottoprogramma >([<lista parametri formali>]) { sezione dichiarativa

corpo del sottoprogramma [return <espressione>;]

}

• Ogni funzione presenta un valore di ritorno che può essere di un qualsiasi tipo predefinito dal linguaggio o definito

dall’utente.

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

Funzioni in C

Procedure in C

• In C non esistono le procedure

• Essa è definita come una funzione con il tipo predefinito void

come valore di ritorno; ovvero non è ritornato alcun valore

associato al nome di quella funzione (ma solo ai parametri

passati per riferimento).

(2)

Elementi di Informatica 3 Prof. G. A. Di Lucca - Univ. del Sannio

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:

– termine dell’esecuzione della funzione (quando si incontra la “}” finale)

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

• 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 scambiare dati con 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.

• Per ciascun parametro deve essere dichiarato il suo tipo.

• Esempio:

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

<parte dichiarativa>

<corpo della funzione >

[return <espressione>;]

}

(3)

Elementi di Informatica 5 Prof. G. A. Di Lucca - Univ. del Sannio

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 nel chiamante)

• è possibile passare i parametri per “riferimento”, utilizzando variabili di tipo puntatore

• 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

Notazione per lo scambio di parametri per riferimento

• Il meccanismo di scambio dei parametri per riferimento (per indirizzo) avviene tramite l’uso di variabili di tipo puntatore;

in tal caso la funzione chiamata sarà in grado di modificare direttamente il valore del parametro effettivo che riceve.

• Notazione nella dichiarazione di una funzione C di un argomento passato per riferimento:

<tipo> <nome_funzione> (

*

<nome_parametro>)

Es:

void proc1(int *A, int B)

passato per riferimento passato per valore

(4)

Elementi di Informatica 7 Prof. G. A. Di Lucca - Univ. del Sannio

• Anche i parametri effettivi nella chiamata alla funzione avranno una forma diversa se passati per valore o riferimento

• Passaggio per indirizzo:

<nome_funzione_chiamata> (&<nome_parametro>) Es.:

square(&numero); //chiamata della funzione square con parametro // effettivo numero passato per riferimento riferendosi all’esempio precedente:

int x, y;

proc1(&y, x); //chiamata della funzione proc1 con parametro effettivo // y passato per riferimento e x per valore

Notazione per scambio di parametri per riferimento

[<direttive di inclusione>]

<dichiarazioni sottoprogrammi>

main ( ) {

<corpo del programma>

}

Struttura di un programma con sottoprogrammi in linguaggio C

#include <stdio.h>

float Area_Tr (int W, int Y);

{ float Area_triangolo;

Area_triangolo = (W*Y)/2;

return Area_triangolo;

} main ( )

{ float base, altezza;

printf (“Immetti valore base\n”);

scanf (“%f”, &base);

printf (“Immetti valore altezza\n”);

scanf (“%f”, &altezza);

if ((base>0)&&(altezza>0))

printf (“Area Triangolo = %f \n”),

Area_Tr(base,altezza));

else printf (“Errore: valore base e/o altezza non maggiori di zero !! \n”);

}

Le dichiarazioni dei

sottoprogrammi vanno fatte prima del main

(5)

Elementi di Informatica 9 Prof. G. A. Di Lucca - Univ. del Sannio

Esempio

#include <stdio.h>

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

{

int a=x*x*x;

return a; //il valore di a è associato al nome ‘cube’

// della funzione e ‘ritornato’ al main

}

main () {

int I;

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

scanf(“%d”, &I);

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

}

Esempio

#include <stdio.h>

// procedure che calcola il cubo di una variabile // il valore del cubo calcolato è associato al // parametro formale a passato per riferimento

void cube(int x, int *a) {

*a = x*x*x;

}

main ()

{ int I, fat;

printf("Immetti numero per calcolarne il cubo\n ");

scanf("%d", &I);

cube (I, &fat);

printf("Cubo = %d \n", fat);

}

(6)

Elementi di Informatica 11 Prof. G. A. Di Lucca - Univ. del Sannio

Conseguenze di errato meccanismo di scambio parametri

#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);

}

Un programma che attiva un sottoprogramma per effettuare lo scambio (swap) dei valori di due variabili

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

ovvero nessuno scambio

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 con il corretto scambio per riferimento

#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=5 b=3

… scambio effettivamente effettuato Ora x e y sono parametri

formali passati per riferimento

(7)

Elementi di Informatica 13 Prof. G. A. Di Lucca - Univ. del Sannio

Sottoprogrammi: un esempio

… un programma per leggere e stampare i valori di array di interi

… una strutturazione in moduli (sottoprogrammi)

main

leggivet stampavet

… ciascun modulo risolve uno specifico problema ...

#include <stdio.h>

void leggivet(int Vet1[ ], int card1) // procedure per leggere da tatstiera i valori { int I; // degli elementi dello array

for (I=0;(I< card1); I++) // Vet1 per riferimento, card1 per valore {printf("immetti Vet[ %d ]= \n”,I) ;

scanf(“%d”, &Vet1[I]);

} }

void stampavet(int Vet1[ ], int card1) // procedure per visualizzare i valori { int I; ; // degli elementi dello array

for (I=0;I<card1; I++) // Vet1 per riferimento, card1 per valore

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

}

… un programma per leggere e stampare i valori di array di interi

Sottoprogrammi: un esempio

(8)

Elementi di Informatica 15 Prof. G. A. Di Lucca - Univ. del Sannio

main ()

{ const card=50;

int Vet[card];

leggivet(Vet,card); // chiama la procedure leggivet // Vet per riferimento, card per valore

stampavet(Vet,card); // chiama la procedure stampavet // Vet per riferimento, card per valore }

Sottoprogrammi: un esempio

#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]);

} }

void stampavet(int Vet1[ ], int card1) { int I; ; for (I=0;I<card1; I++)

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

}

main ()

{ const card=50;

int Vet[card];

leggivet(Vet,card);

stampavet(Vet,card);

}

… il programma per leggere e visualizzare i valori di array di interi usando sottoprogrammi:

• La procedure leggivet per la lettura del valore degli elementi da tastiera

• La procedure stampavet per visualizzare i valori degli elementi sul monitor

Sottoprogrammi:

un esempio

(9)

Elementi di Informatica 17 Prof. G. A. Di Lucca - Univ. del Sannio

Sottoprogrammi:

un esempio

void leggivet_riemp(int Vet1[],int card1, int *riemp1) { int I;

do

{ printf("immetti riemp\n");

scanf("%d",&(*riemp1));

}

while(*riemp1>card1);

for (I=0;(I<*riemp1); I++)

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

} }

... nel caso di riempimento parziale ...

... il parametro riemp1 passato per riferimento indicante il riempimento

#include <stdio.h>

void leggivet_riemp(int Vet1[],int card1, int *riemp1) { int I;

do

{ printf("immetti riemp\n");

scanf("%d",&(*riemp1));

}

while(*riemp1>card1);

for (I=0;(I<*riemp1); I++)

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

} }

void stampavet_riemp(int Vet1[ ],int riemp1) { int I; ; for (I=0;I<riemp1; I++)

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

} main () { const card=50;

int Vet[card], riemp;

leggivet_riemp(Vet,card, &riemp);

stampavet_riemp (Vet, &riemp);

}

Sottoprogrammi:

un esempio

Il programma per lettura e visualizzazione dei valori nel caso di riempimento parziale dello array ...

(10)

Elementi di Informatica 19 Prof. G. A. Di Lucca - Univ. del Sannio

Prototipo di una funzione

Il prototipo di una funzione rappresenta una dichiarazione di funzione (indicandone la sola intestazione) che precede la sua completa definizione.

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

int function(int,char); // indicati solo i tipi dei // parametri formali

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

Lo scopo dei prototipi delle funzioni è quello di permettere al compilatore di compiere il controllo sui nomi della funzione e dei 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;

}

(11)

Elementi di Informatica 21 Prof. G. A. Di Lucca - Univ. del Sannio

Prototipi di funzione

• L’inserimento dei prototipi prima della definizione di una funzione, permette al compilatore, quando incontra la dichiarazione del prototipo di conoscere e controllare il numero ed i tipi degli argomenti.

• 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.

#include <stdio.h>

void leggivet(int Vet1[ ],int card1); // prototipo procedure leggivet

void stampavet(int Vet1[ ],int card1); // prototipo procedure stampavet

main ()

{ const card=5;

int Vet[card];

leggivet(Vet,card);

stampavet(Vet,card);

}

… il programma per leggere e stampare i valori di array di interi usando i prototipi di funzione

Sottoprogrammi: esempio

(12)

Elementi di Informatica 23 Prof. G. A. Di Lucca - Univ. del Sannio

#include <stdio.h>

void leggivet(int Vet1[ ], int card1) void stampavet(int Vet1[ ], int card1) main ()

{ const card=50;

int Vet[card];

leggivet(Vet,card);

stampavet(Vet,card);

}

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

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

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

} }

void stampavet(int Vet1[ ], int card1) { int I; ; for (I=0;I<card1; I++)

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

}

… il programma per leggere e visualizzare i valori di array di interi usando i prototipi di leggivet e stampavet

Sottoprogrammi:

esempio

Sottoprogrammi in file separati

• 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 memorizzati in file diversi, dovrà essere indicata una direttiva di inclusione (#include) che indica il file sorgente da includere contenente il/i sottoprogramma/i chiamato/i.

(13)

Elementi di Informatica 25 Prof. G. A. Di Lucca - Univ. del Sannio

Sottoprogrammi in file separati

#include <stdio.h>

#include <C:\cube.h> /*include il file cube.h, registrato su C:

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 è memorizzata 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

per DevC++ la libreria di inclusione è la cartella include

#include <stdio.h>

#include <\Dev-Cpp\ProgC2015\leggivet.h>

#include <\Dev-Cpp\ProgC2015\stampavet.h>

main ()

{ const card=5;

int Vet[card];

leggivet(Vet,card);

stampavet(Vet,card);

}

… un programma per leggere e visualizzare i valori di un array di interi

… usando file separati per ciascun modulo ...

Sottoprogrammi: esempio

main

leggivet stampavet

(14)

Elementi di Informatica 27 Prof. G. A. Di Lucca - Univ. del Sannio

#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

... ricordare che quando un parametro formale è un array questo viene passato

automaticamente per riferimento

… i due sottoprogrammi … in file separati ….

Sottoprogrammi: qualche esempio

Esempio

Definizione del problema: Trovare il valore minimo tra gli elementi di un array di interi, con cardinalità 50, ed indicarne la posizione (se vi sono più elementi con lo stesso valore minimo va indicata la posizione del primo elemento ‘minimo’). Lo array può essere ‘riempito’ parzialmente.

Definizione dei dati del problema:

I: il riempimento; il valore di ciascun elemento

Pi: il riempimento non può essere maggiore della cardinalità dell’array U: il valore minimo nello array; la posizione dell’elemento con valore minimo

Pu: la posizione del minimo non maggiore del riempimento

(15)

Elementi di Informatica

Prof. G. A. Di Lucca - Univ. del Sannio 29

Esempio - il programma C

#include<stdio.h>

#include <C:\Dev-Cpp\ProgC2015\leggivet.h>

#include <C:\Dev-Cpp\ProgC2015\stampavet.h>

#include <C:\Dev-Cpp\ProgC2015\min_in_vet.h>

main()

{ const int cardinalita=50;

int Vet[cardinalita], I, riemp,MIN, POS;

do

{ printf (“quanti elementi vuoi inserire?\n”);

scanf (“%d”, &riemp);

}

while ( riemp>cardinalita);

leggivet(Vet,riemp);

stampavet(Vet,riemp);

min_in_vet(Vet, riemp, &MIN, &POS);

printf (“il valore minimo = %d si trova nella posizione numero%d\n” , MIN, POS);

system (“Pause”);

}

void min_in_vet(int VET1[], int riemp1, int *MIN, int *POS) {

// Cerca il valore minimo nello array int I;

*MIN = VET1[0];

*POS=0;

for (I=1; I< riemp1; I++) {

if (VET1[I]<*MIN) {

*MIN=VET1[I];

* POS=I;

} } }

Esempio - il programma C

(16)

Elementi di Informatica Prof. G. A. Di Lucca - Univ. del Sannio

#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] );

}

Sottoprogrammi leggivet e stampavet

Riferimenti

Documenti correlati

Si ricorda al lettore che i problemi fino ad ora affrontati sono stati ipotizzati per tener conto dell’ imprevedibilità del fenomeno, per questa ragione le soluzioni proposte

• Il prototipo prototipo di una funzione è una dichiarazione di funzione antecedente alla sua definizione: permette al compilatore di compiere il controllo sui tipi degli argomenti

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

È analizzata la sequenza di caratteri costituenti ciascuna istruzione e sono identificati i simboli effettivi (token), quali nomi di identificatori, costanti, operatori,

• L’inserimento dei prototipi prima della definizione di una funzione, permette al compilatore, quando incontra la dichiarazione del prototipo di conoscere e controllare il numero

• L’inserimento dei prototipi prima della definizione di una funzione, permette al compilatore, quando incontra la dichiarazione del prototipo di conoscere e controllare il numero

• L’inserimento dei prototipi prima della definizione di una funzione, permette al compilatore, quando incontra la dichiarazione del prototipo di conoscere e controllare il numero

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