*
 * Fino ad ora i nostri programmi sono stati visti come una sequenza di
 * istruzioni all'interno della funzione main().
 * Pero' abbiamo chiamato funzioni gia' disponibili nella libreria standard,
 * come printf() e scanf(). Non abbiamo fatto altro che chiamare delle
 * funzioni esterne al blocco di istruzioni main(), passandogli anche degli
 * argomenti, ad esempio:
 *
 *	printf("Salve mondo");
 *
 * L'argomento che passiamo al printf e' "Salve Mondo": non facciamo altro
 * che chiamare una subroutine gia' pronta che si occupa di stampare
 * caratteri a video, passandogli il testo da stampare.
 * Da notare che subroutine si puo' tradurre in "sottoprogramma".
 * Ora vedremo come creare delle nostre funzioni, che potremo usare per
 * rendere piu' semplice il riutilizzo di routine gia' scritte, e per
 * aumentare la leggibilita' del listato.
 * La nostra funzione sara' un blocco di istruzioni ISOLATO e posto dopo
 * la fine della funzione main (puo' essere messa anche prima, tanto il
 * programma parte comunque dalla funzione main).
 * Per eseguire quel blocco di istruzioni da un qualsiasi punto all'interno
 * della funzione main, dovremo fare una cosa che si puo' tradurre in:
 * "Salta ad eseguire le istruzioni che trovi nel blocco della funzione,
 * poi ritorna qua a finire di eseguire le istruzioni di Main".
 * Per motivi di standard, dovremo anche dichiarare all'inizio del programma
 * le nostre funzioni indicandone i parametri input/output (prototipo).
 * Di solito si fa in modo che una funzione svolga un unico compito, almeno
 * quando occorre svolgere nuovamente quel dato compito basta richiamarla.
 * Una funzione normalmente richiede dei dati in ingresso e opzionalmente
 * produce un risultato, ossia il valore restituito. Comunque certe funzioni
 * possono non richiedere dati in ingresso e/o non restituire alcun valore.
 * Facciamo degli esempi: una funzione che non ci restituisce nessun valore,
 * ma richiede i dati di ingresso, potrebbe essere una funzione dedicata alla
 * stampa di un numero: in entrata vuole il testo da stampare, e non ci da
 * niente all'uscita.
 * Lo scanf, per esempio, in piu' ci restituisce il valore inserito da
 * tastiera, se vi ricordate. Quindi e' una funzione che vuole dei parametri
 * in entrata e ce ne restituisce in uscita.
 * Una funzione che non richiede dati in ingresso e che non ne restituisce
 * in uscita potrebbe essere una funzione che pulisce lo schermo, ad esempio.
 * Una che non richiede dati in ingresso e ne da in uscita potrebbe essere
 * una routine che ci da un numero a caso.
 * Vediamo il formato di una funzione:
 *
 *	TipoRitorno NomeFunzione(Lista tipo e nome argomenti passati)
 *	{
 *	  corpo della funzione
 *	}
 *
 * SpecificaTipo = dichiara il tipo di valore (int, float, ecc.) che la
 *		   funzione restituisce attraverso l'istruzione return.
 * NomeFunzione = Il nome della funzione, che scegliamo a nostro piacimento,
 *		  basta che non sia uguale ad una delle parole chiave del C.
 * Lista Argomenti = Una lista di nomi di variabili separate da virgole,
 *		     preceduti dal tipo di variabile stesso (int, float...)
 *		     per indicare i parametri in ENTRATA della funzione,
 *                   ovvero i dati che gli vengono passati alla chiamata.
 *
 * Ecco un esempio:
 *
 *	int somma(int a,int b)	* Funzione che restituisce un valore INT *
 *				* ed ha 2 parametri in entrata sempre INT *
 *	{
 *	   return(a+b);		* Restituisci il risultato di a+b
 *	}
 *
 * Per chiamare questa funzione dal corpo di main() si fa in questo modo:
 *
 *	somma(variabile1,variabile2)
 *
 * Pero' dovremo salvare il valore restituito, in una variabile.
 * Ad esempio, potremmo mettere un:
 *
 *	papero = somma(pippo,pluto);
 *
 * Naturalmente si faceva prima a sommare direttamente, ma per capire come
 * fare una funzione e' un'esempio lampante.
 * Da notare che non e' necessario passare alla funzione variabili con gli
 * stessi nomi di quelle usate nella funzione (che in questo caso si chiamano
 * a,b), basta che siano 2 variabili dello stesso tipo (in questo caso int).
 * Abbiamo incontrato l'istruzione return, che serve per "ritornare" ed
 * eventualmente "restituire" qualcosa al programma che ha chiamato la
 * funzione: nel nostro caso restituisce anche un valore.
 * Ora sorge un dubbio: anche main() e' una funzione, eppure la dichiariamo
 * senza specificarne il tipo, senza argomenti, e la abbiamo fin qui
 * terminata senza il return!!!
 * Infatti non siamo stati molto rigorosi. I compilatori solitamente assumono
 * che se non si specifica il tipo, questo e' sempre INT, e se non si mettono
 * argomenti, questi non ci sono. Per essere pignoli si dovrebbe mettere un
 * (void) al posto di (), infatti void significa "vuoto".
 * Inoltre, se non e' presente il return, il compilatore restituisce 0.
 * Riscriviamo rigorosamente il nostro primo programmino:
 *
 *	int main(void)
 *	{
 *          printf("Pippo\n");
 *	    return(0);
 *	}
 *
 * In questo modo dichiariamo esplicitamente quello che prima era stato
 * assunto per default dal compilatore: siamo piu' coscenti della situazione.
 * Da notare che lo 0 e' restituito al DOS alla fine del programma, per
 * tranquillizzarlo sulla corretta riuscita del nostro programmino.
 * Il DOS comunque non si interessa molto a questo valore...
 * Fino ad ora siamo stati poco  rigidi sullo standard ANSI per semplificare
 * le cose, ma da ora in avanti non sgarriamo piu'.
 * Proprio per questo, occorre precisare un'altra cosa: se nel listato
 * mettiamo prima le nostre funzioni, poi il main() che le chiama, non ci
 * saranno errori, infatti quando il compilatore trova il riferimento alla
 * nostra funzione somma() all'interno della funz. principale main(), sa gia' i
 * i suoi parametri in entrata e in uscita, perche' ha gia' letto la sua
 * dichiarazione (la compilazione parte dall'alto e scende!).
 * Se invece mettessimo prima il main(), poi la nostra funzione, il povero
 * compilatore si troverebbe di fronte un fantomatico somma() di cui non sa
 * niente, perche' viene definito piu' sotto, dove non e' ancora arrivato
 * a compilare. Non potendo verificare se a somma() sono passati i tipi di
 * variabile giusti, interrompe la compilazione.
 * Per questo e' stato reso possibile (con lo standard ANSI) dichiarare
 * anticipatamente le nostre funzioni, all'inizio del listato, in modo da
 * non "spaventare" il compilatore. Atrimenti avremmo dovuto sempre mettere
 * prima le nostre funzioni, infine, in fondo al listato, il main().
 * Questa anticipazione di dichiarazione e' detta "prototipo", ed ha questa
 * forma:
 *
 *	TipoRitorno NomeFunzione(TipoParametro1, TipoParametro2);
 *
 * Ecco il nostro esempio pratico:
 *
 *	int somma(int, int);
 *
 * In pratica e' come la dichiarazione "vera", ma si termina con un punto e
 * virgola e al posto dei parametri (tipo+nomevariabile) si mette solo il
 * loro tipo: in questo modo il compilatore sa da subito che la funzione
 * somma() ha 2 parametri di tipo INT in entrata ed uno in uscita, sempre di
 * tipo INT.
 * Un prototipo e' un modello limitato di un'entita' piu' completa che
 * deve arrivare dopo.
 * Ora vediamo un programma che, oltre a chiamare una funzione, e' anche
 * scritto in modo rigoroso:
*/

#include <stdio.h>	/* Includiamo la libreria standard */

/* Forniamo una dichiarazione anticipata (prototipo) delle nostre funzioni */

int somma(int,int);

/* Funzione principale e inizio del programma */

int main(void)		/* Funzione principale, eseguita per prima */
{			/* Inizio della funzione main() */

	int pippo,pluto,papero;	/* Definiamo 3 variabili intere */

	printf("\nDammi un numero: ");
	scanf("%d",&pippo);
	printf("\nDammi un'altro numero: ");
	scanf("%d",&pluto);
	papero = somma(pippo,pluto);	/* Chiamata della funzione! */
	printf("\nLa somma dei due e' %d\n", papero);
	return(0);	/* la funzione main restituisce uno 0 intero */
} 			/* Fine della funzione main() */

/* Ora definiamo una funzione chiamata somma(), che in entrata richiede 2
 * variabili di tipo intero, e in uscita restituisce un'altro numero intero,
 * somma dei 2 in entrata:
 */

int somma(int a,int b)
{
	printf("Sto calcolando la somma... com'e' difficile!!!");
	return(a+b);
}

/* Comunque, se non vi disturba mettere il main() in fondo al listato, e'
 * preferibile mettere all'inizio le funzioni, in modo da risparmiarci di
 * scrivere i prototipi, e soprattutto di cambiarli ogni volta che si
 * cambiano i parametri delle nostre funzioni, che naturalmente non saranno
 * le definitive al primo colpo.
 * Una cosa da notare e' che la funzione somma() usa 2 variabili con nome
 * diverso rispetto a quello delle variabili usate dalla funzione main()
 * per chiamarla.
 * Infatti le due variabili a,b sono LOCALI, usate solo dalla funzione, ed
 * assumeranno i valori passati con "somma(pippo,pluto)": il valore di pippo
 * sara' copiato in a, quello di pluto in b e la loro somma sara' data in
 * uscita, e copiata in papero.
 * Altra cosa da notare e' che in vecchi programmi C, scritti prima che si
 * consolidasse lo standard ANSI, si potrebbero trovare dichiarazioni
 * di questo tipo:
 *
 *	int somma(a,b)
 *	int a,b;
 *	{
 *	...
 *	}
 *
 * Il nuovo sistema e' molto piu' compatto, dato che si evita di definire
 * a parte il tipo delle variabili usate come parametri in entrata.
 */