Linguaggio C (1)

Stefano Petrarca
Conservatorio S. Cecilia - Roma

Altre istruzioni di controllo

- Cicli enumerativi

Nel caso di cicli enumerativi cioè quelli in cui si conosce a priori il numero di ripetizioni, è possibile usare l'istruzione for(<inizializzazione>;<condizione>;<incremento>) che è più compatta ed efficiente rispetto agli altri tipi di ciclo (ad esempio do....while); il primo campo contiene, normalmente, l'inizializzazione dell'indice del ciclo, il secondo la condizione di permanenza nel ciclo, il terzo l'incremento dell'indice. La figura sottostante mostra un esempio relativo all'inizializzazione dei valori di un array.

Ciclo enumerativo In C usando do ... while(); In C usando for()
ciclo1.gif (2324 byte)

void main()
{
  int i=0, N=10;
  do
  {
   scanf("%d",&x[i]);
   i++;
  }
  while(i< N);
}
void main()
{
  int i, N=10;
  for(i=0;i< N;i++)
  {
   scanf("%d",&x[i]);
  }
}

Pertanto, in tutti i programmi che prevedono l'elaborazione ciclica di array di dimensione nota è conveniente usare il ciclo for.

 

- Selezioni multiple

L'istruzione di selezione che già conosciamo permette di creare una diramazione nel flusso del programma in conseguenza della verità o falsità di una proposizione logica. Nel caso in cui vogliamo creare una diramazione con più di 2 bracci in dipendenza dai valori che può assumere una variabile possiamo usare l'istruzione switch(). Ad esempio se vogliamo realizzare un programma che visualizzi un certo messaggio fra 4 disponibili introducendo da input un valore numerico compreso fra 1 e 4, possiamo agire come segue:

Selezione multipla

In C usando if ... else In C usando switch()

switch1.gif (2318 byte)

int x;
scanf("%d",&x);
if(x==1) printf("Ciao");
else
 if(x==2) printf("Hi");
 else
  if(x==3) printf("Bye");
  else
   if(x==4) printf("Ave");
....
int x;
scanf("%d",&x);
switch(x)
{
 case 1: printf("Ciao");
         break;
 case 2: printf("Hi");
         break;
 case 3: printf("Bye");
         break;
 case 4: printf("Ave");
         break;
}
....

Dall'esempio possiamo vedere la maggiore concisione e pulizia del codice usando l'istruzione switch() rispetto all'uso di una catena di istruzioni if ... else. Ogni volta che conosciamo a priori tutti i casi possibili associati ad una variabile di controllo possiamo usare tale istruzione. Da notare la complessa sintassi dell'istruzione: ogni gruppo di istruzioni relativo ad ogni caso è indipendente dagli altri casi; inoltre, l'istruzione break (non obbligatoria) che compare alla fine del gruppo associato ad ogni caso serve per saltare tutti gli altri gruppi ed evitare eventuali malfunzionamenti dovuti ad un uso scorretto della variabile di controllo.

 

- Funzioni

Quando la struttura del programma è molto complessa conviene suddividere il codice usando i sottoprogrammi. L'uso di questi ultimi è consigliabile anche quando, all'interno del programma, esistono gruppi identici di istruzioni ripetuti che eseguono lo stesso compito. Un sottoprogramma è una parte di codice indipendente che svolge un determinato compito e viene mandato in esecuzione da un programma chiamante (che, a sua volta, può essere un sottoprogramma). Al termine dell'esecuzione del sottoprogramma, il controllo ritorna al programma chiamante che prosegue nel suo lavoro partendo dall'istruzione successiva a quella di chiamata al sottoprogramma.
All'atto della chiamata a sottoprogramma possono essere passati a questo degli argomenti all'interno di variabili; queste ultime e quelle che sono dichiarate all'interno del sottoprogramma, sono dette variabili locali e sono visibili (cioè possono essere usate) solo all'interno del sottoprogramma. Le variabili globali, al contrario, sono visibili dappertutto nel programma e sono dichiarate al di fuori di tutti i moduloi di programma.
Normalmente si fa distinzione fra funzioni e procedure; un sottoprogramma viene chiamato funzione se, al termine della sua esecuzione, restituisce un valore al chiamante; viene invece detto procedura se non restituisce valori. Nel linguaggio C esistono solo funzioni il cui corpo consiste di moduli di programma separati dal programma principale (il
main()); una funzione va definita in base al tipo del suo valore di ritorno: ci saranno, quindi, funzioni di tipo intero, floating-point, carattere, etc. che restituiranno rispettivamente un valore intero, reale, carattere, etc. Una funzione che non restituisce valori (una procedura) va dichiarata di tipo void. La definizione ANSI del C richiede, inoltre, che ogni funzione abbia un prototipo che definisca a priori il tipo del valore di ritorno e il tipo di ogni argomento passato dal chiamante.
Già conosciamo l'uso delle funzioni; ad esempio, quando scriviamo

	#include <stdio.h>
	void main()
	{
		printf("Hello world\n");
	}

printf() è una funzione di libreria, cioè una particolare categoria di funzioni fornite insieme al compilatore C e, quindi, sempre disponibili; i loro prototipi sono definiti negli header file che sono anch'essi forniti dai realizzatori del compilatore; ad es., il prototipo di printf() fa parte del file stdio.h. Anche main() stessa va considerata una funzione anche se molto particolare; normalmente è di tipo void e può avere degli argomenti di passaggio; questi ultimi saranno analizzati quando parleremo dei puntatori. Vediamo un esempio di funzione realizzando un programma che permette di visualizzare, a richiesta, una potenza di 2; sarà definita allo scopo una funzione che calcola la potenza n-ma di un numero e sarà chiamata dal main() con gli argomenti introdotti dall'utente tramite la tastiera.

#include <stdio.h> //prototipi delle funzioni di libreria
#include <conio.h> // ''
double potenza2(int); //prototipo della funzione
void main()
{
 int esponente;
 double p2;
 char c;
 printf("Calcolo delle potenze positive e negative di 2\n\n");
 do
 {
	printf("Introduci l'esponente: ");
	scanf("%d",&esponente); //input argomento da tastiera
	p2 = potenza2(esponente); //chiamata della funzione
	printf("2^%d = %lf\n",esponente,p2);
	printf("Un'altra potenza?[s/n] ");
	c = getch(); //attesa di un carattere dalla tastiera
 }
 while(c == 's'); //continua a richiedere calcolo se si risponde con il carattere 's'
}
	
//intestazione della funzione (i tipi devono corrispondere a quelli del prototipo)
double potenza2(int espo)
{
	int i,n;
	double p = 1;
	if(espo < 0) n = -espo;
	else n = espo;
	for(i=0;i<espo;i++)
	{
		p*=2; //calcolo della potenza di 2
	}
	if(espo < 0) p = 1/p;
	return(p); //istruzione che restituisce il valore calcolato al chiamante
}

Da notare l'uso dell'istruzione return alla fine della funzione per consentire il passaggio del valore di ritorno al chiamante. L'istruzione p*=2 è equivalente a p = p * 2.
L'output del programma sarà il seguente nel caso che venga usato il Visual C++ in console mode

pot2.gif (13743 byte)

 


Pagina iniziale

Matematica

Informatica

Programma

Bibliografia