Le funzioni

17 marzo 2006

Le funzioni sono uno degli strumenti più potenti del C; esse infatti permettono un notevole risparmio e riuso del codice, con ovvii vantaggi del programmatore. Le funzioni esistono più o meno in tutti i linguaggi e vengono chiamate anche procedure o subroutine.

Alcuni linguaggi fanno distinzione tra funzioni che ritornano un valore e quelle che, invece, non ritornano valori; il C assume che ogni funzione ritorni un valore, questo accade utilizzando l’istruzione return seguita, eventualmente, da un valore; se non si mette l’istruzione return, nessun parametro deve essere passato quando si chiama la funzione. Prendiamo ad esempio, la definizione di una funzione che prende un double ed un int e fa un elevamento a potenza, restituendo il risultato:

double elevamento_potenza(double valore, int potenza)
{
  double valore_ritorno = 1.0;
  int i;

  for(i=0; i<potenza; i++)
  {
    valore_ritorno *= valore;
  }
  
  return(valore_ritorno);
}

Analizzando questa funzione possiamo innanzitutto far notare che il calcolo eseguito, per quanto complesso e poco ortodosso, restituisce il valore corretto anche quando la potenza vale zero; iniziamo, dunque, a studiare il codice nel dettaglio:

double elevamento_potenza(double valore, int potenza)

Questa è la definizione della funzione, che ci dice il tipo del valore di ritorno (double), il nome della funzione (elevamento_potenza()) e la lista di argomenti usati dalla funzione con il tipo (double e int) ed il nome (valore e potenza) corrispondente;

return(valore_ritorno);

Quando si raggiunge un’istruzione “return“, il controllo del programma ritorna a chi ha chiamato la funzione. Il valore ritornato è quello posto dopo la parola return;se si chiude la funzione prima di mettere un’istruzione “return“, la funzione ritorna automaticamente, ed il valore ritornato potrebbe non avere un significato valido.

Il valore ritornato può essere manipolato a piacimento, infatti se una funzione restituisce un risultato, possiamo assegnarlo, ad esempio, ad una variabile che poi potremmo usare all’interno del programma come qualsiasi altra variabile;

double val = 100.0;
int pot = 3;
double risultato = elevamento_potenza(val, pot);

Esistono anche funzioni che non ritornano alcun valore, in questo caso si parla di funzioni void, come mostrato di seguito:

void stampa_errore(int linea)
{
  fprintf(stderr, “Errore: linea %dn”, linea);
}

Una funzione void non deve contenere necessariamente un’istruzione return, anche se essa può essere usata per uscire dalla funzione in maniera opportuna, un po’ come l’uso del “break” all’interno dei cicli.

In questo caso abbiamo presentato anche l’uso dell’istruzione fprintf(), una variante della printf(), che spiegheremo in dettaglio nella lezione 16; basti sapere che in questo caso abbiamo stampato il messaggio di errore sullo “stderr” che può essere un file o un messaggio a video (generalmente quest’ultimo).

Per richiamare la funzione, basta, ovviamente, scrivere il nome con, tra gli argomenti, il numero di linea in cui si è verificato l’errore;

int linea_err = 14;
stampa_errore(linea_err);

Va fatta una piccola nota riguardante le funzioni, in merito alla prototipazione delle funzioni, ovvero la creazione di prototipi. Un prototipo di una funzione non è altro che la sua dichiarazione, senza specificare il corpo della funzione stessa; si scrive, quindi, solo la dichiarazione iniziale comprendente il nome ed il tipo restituito dalla funzione, e gli argomenti passati come parametro; questo avviene perché ogni funzione è utilizzabile solamente quanto è stata dichiarata, quindi se in un pezzo di codice, prima di dichiarare la funzione, voglio usare tale funzione, non posso farlo, perché “fisicamente” non è ancora stata creata. Creando dei prototipi si ovvia a questo problema e si hanno dei vantaggi anche in termini di funzionalità ed organizzazione del codice stesso. Ecco due esempi, il primo errato, il secondo corretto:

// questo non funziona
#include <stdio.h>

int main()
{
  int var = 5;
  stampa_doppio(var);
}

void stampa_doppio(int variabile)
{
  printf(“Il doppio di %d è %d “, variabile, 2*variabile);
}

/* ——————————————————– */

// questo funziona
#include <stdio.h>

void stampa_doppio(int variabile); // prototipo della funzione

int main()
{
  int var = 5;
  stampa_doppio(var);
}

void stampa_doppio(int variabile)
{
  printf(“Il doppio di %d è %d “, variabile, 2*variabile);
}

In C, quando si passano gli argomenti (variabili) alle funzioni, bisogna prestare attenzione al passaggio di array ad una o più dimensioni; la regola dice che la prima dimensione dell’array può non essere specificata, mentre la seconda e le altre devono esserlo. Un esempio chiarirà meglio il concetto:

void stampa_array_uni(int dim, int array_uni[])
{
  int i;
  for(i=0; i < dim; i++)
  {
    printf(“%d “, array_uni[i]);
  }
}

void stampa_array_bid(ind dimx, int dimy, int array_bid[][6]);
{
  int i, j;
  for(i=0; i < dimx; i++)
  {
    for(j=0; j < dimy; j++)
    {
      printf(“%d “, array_uni[i][j]);
    }
  
    printf(“n”);
  }
}

Esempio Pratico

(Visualizza il sorgente completo)

All’interno del programma vengono usate svariate funzioni. Alcune esclusivamente create per inserire/modificare/eliminare i contatti della rubrica, altre, come nel caso della funzione substring, per una funzione di utilità non disponibile in C.

Di seguito mostriamo la dichiarazione dei prototipi delle funzioni all’inizio del programma e la funzione substring().

45   // Prototipi delle funzioni
46   void visualizzaContatto(struct elemento* p);
47   struct elemento *aggiungiContatto(struct elemento *p);
48   struct elemento *modificaContatto(struct elemento *p);
49   struct elemento *rimuoviContatto(struct elemento *p);
50   struct elemento *leggiDaFile(struct elemento *p);
51   int salvaSuFile(struct elemento *p);
52   void substring(char *dest, char *source, int i_base, int i_dim);
53   void pausa();

[...]

47   /*
548   * Funzione che prende una sottostringa partendo da un’indice
549   * base per un numero di caratteri pari a dimensione
550   */
551  void substring(char* dest, char *source, int i_base, int i_dim)
552  { // substring() – OPEN
553  
554    int i = 0;
555  
556    for (i=i_base; i<i_dim+1; i++)
557    { // FOR – OPEN
558  
559      dest[i-i_base] = source[i];
560  
561    } // FOR – CLOSE
562  
563    dest[i]=’�’;
564
565    return;
566
567  } // substring() – CLOSE

Tutte le lezioni

1 ... 23 24 25 ... 47

Se vuoi aggiornamenti su Le funzioni inserisci la tua e-mail nel box qui sotto:
 
X
Se vuoi aggiornamenti su Le funzioni

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy