PROCEDURE E FUNZIONI (SOTTOPROGRAMMI)

Ogni linguaggio di programmazione offre dei costrutti per decomporre un programma in sottoparti, dette genericamente sottoprogrammi.
Esistono due tipologie di sottoprogrammi:
PROCEDURA
una sottoparte di programma che corrisponde ad uno statement (istruzione);
FUNZIONE
una sottoparte di programma che corrisponde ad una espressione di un certo tipo.
Ogni sottoprogramma è caratterizzato da:
NOME
per identificare e usare, anche più volte, tale sottoparte;
PARAMETRI (anche nessuno)
i sottoprogrammi possono essere parametrizzati su valori, variabili, file, altri sottoprogrammi, ...;
BODY (CORPO)
il testo che definisce la sottoparte vera e propria.
La struttura di un programma diventa ora
SUBPROGRAM DECLARATIONS
MAIN

PARAMETRI

I parametri di un sottoprogramma vengono elencati nella dichiarazione del sottoprogramma stesso (i cosidetti parametri formali) e possono essere di diversa natura.
Le tipologie dei parametri più comuni sono:
VALORI (di un qualche tipo di dato del linguaggio)
la dichiarazione del parametro (parametro formale) ha la forma generica
value IDENTIFIER : TYPE
mentre il corrispondente parametro attuale è semplicemente un'espressione EXP di tipo TYPE.

Ogni linguaggio può poi precisare come avviene il passaggio del parametro più dettagliatamente; per esempio

per nome
ogni occorrenza di IDENTIFIER nel corpo del sottoprogramma viene rimpiazzata dal testo di EXP
per copia
IDENTIFIER è una variabile dichiarata implicitamente all'inizio del corpo del sottoprogramma che viene inizializzata con il valore di EXP al momento della chiamata; in certi linguaggi non è più possibile assegnare un nuovo valore a tale variabile.
VARIABILI (di un qualche tipo del linguaggio)
la dichiarazione del parametro (parametro formale) ha la forma generica
variable IDENTIFIER : TYPE
mentre il corrispondente parametro attuale è semplicemente una variabile VAR di tipo TYPE;
più precisamente o una variabile di un tipo semplice o una componente di una variabile di un tipo strutturato, cioè ogni cosa che può essere trovata a sinistra di un'assegnazione.
Seguendo la metafora variabile=scatola, in questo caso il parametro formale è un nome generico di scatola, mentre quello attuale è il nome di una scatola particolare, cioè il sottoprogramma è parametrizzato su una scatola.
SOTTOPROGRAMMI
Ogni linguaggio di programmazione precisa se e quali forme di sottoprogrammi possono essere usate per parametrizzare altri sottoprogrammi
FILE
Ogni linguaggio di programmazione permette di parametrizzare i sottoprogrammi con dei file; in questi casi il parametro formale è un nome generico di un file di un certo tipo, mentre quello attuale deve essere il nome di un file dello stesso tipo esistente.
Chiaramente all'interno dei sottoprogrammi possiamo utilizzare tutti i costrutti del linguaggio, quindi per esempio chiamare altri sottoprogrammi ed anche dichiarare sottoprogrammi che saranno utilizzati solamente al loro interno.
ESERCIZIO
  1. Definire una forma di sottoprogrammi per il calcolatore antropomorfo, precisando quali siano i parametri ed il modo in cui sono passati.

USO DEI SOTTOPROGRAMMI

I sottoprogrammi sono i costrutti più semplici ed usati per strutturare ed organizzare i programmi, allo scopo di
migliorare la loro leggibilità
il programma è suddiviso in sottoparti ognuna indicata da un nome significativo (un po' come i capitoli ed i sottocapitoli in un libro).
questa scomposizione è importante per poter permettere modificare, correggere, ed aggiornare i programmi.
favorire la loro scrittura corretta,
poichè è più facile produrre correttamente piccoli sottopezzi di programmi, ed inoltre la scomposizione in pezzi permette di controllare più facilmente la struttura complessiva del programma
permettere di riutilizzare parti già sviluppate
se in un programma occorre fare più volte le stesse cose utilizzando i sottoprogrammi il codice relativo si scrive una volta sola (nella dichiarazione) e poi si riusa (nelle chiamate); inoltre è possibile riusare sottoprogrammi scritti da altri o da noi stessi in altre occassioni
favorire l'uso di metodi per il loro sviluppo
(es. sviluppo top-down e bottom up).

I SOTTOPROGRAMMI IN C

Il linguaggio C ha la possibilità di dichiarare ed usare sottoprogrammi sia di tipo procedura che di tipo funzione, anche se a livello di terminologia essi sono chiamati sempre funzioni, e le procedure sono semplicemente delle funzioni che ritornano un valore di un tipo speciale, void, che ha un unico valore.

Inoltre il C ha solo parametri valore, e pertanto gli altri tipi devono essere ottenuti in modo indiretto utilizzando i puntatori.

La forma di una dichiarazione di funzione in C è:

TYPE IDENTIFIER ( PARAMETERS )
BLOCK
TYPE
il tipo dei valori ritornati dalla funzione, non può essere un array. Si usa void per le procedure (che sono infatti delle funzioni che non ritornano niente).
IDENTIFIER
il nome della funzione
PARAMETERS
le dichiarazoni dei parametri formali. Si usa void quando la funzione non ha alcun parametro.
I parametri, che sono tutti di tipo valore e sono passati per copia, si dichiarano semplicemente premettendo il tipo al nome del parametro e si separano con virgole.
BLOCK
è il corpo della funzione (un blocco), e quindi può contenere dichiarazioni di variabili locali, cioè utilizzate solo all'interno della funzione.
Se il sottoprogramma è una vera funzione, il C fornisce lo statement
return(EXPR);
per terminare il calcolo e ritornare il valore della funzione, che è giusto il valore di EXPR.
La forma di un programma C con dichiarazioni di funzioni è semplicemente una lista di dichiarazioni di funzioni e un main, come prima.
Notare che il main è semplicemente una procedura di nome main senza parametri, scritta usando la sintassi di una versione più vecchia del C.
ESEMPI
funzione che calcola il fattoriale
#include <stdio.h>

int Fatt(int n)
{  
    if(n < 0)
       printf("Il numero non puo\' essere negativo\n");
    else if(n == 0)
       return(0);
    else{
       int f;
       
       f = 1;
       while(n >= 1){
           f = f * n;
           n = n-1;
       };
       return(f);
   };
}

main(){
    int n, f; 

    printf("dare il numero\n");
    scanf("%d",&n);
    f = Fatt(n);
    printf("Il fattoriale di %d e\' %d \n",n, f);
    
}
procedura per stampare una matrice
#include <stdio.h>
#define DIM 100

void Stampa_Mat(int m[DIM][DIM])
/*stampa m sullo standard output riga per riga*/
{  
    int i,j;
    
    for(i=0; i < DIM; i=i+1){
        for(j=0; j  < DIM; j=j+1)
            printf("%7d ",m[i][j]);
        printf("\n");
    }
}

main(){
    int a[DIM][DIM], i, j, s; 

    printf("dare la matrice su una unica riga\n");
    for(i=0; i  < DIM; i=i+1)
        for(j=0; j < DIM; j=j+1){
            scanf("%d",&s); a[i][j]=s;};

    Stampa_Mat(a);    
}}