next up previous contents index
Next: Conversioni esplicite Up: Funzioni Previous: Funzioni in C++   Indice   Indice analitico

Ancora sulle funzioni

Per ora gli argomenti utilizzati dalle funzioni sono passati esclusivamente per valore: le variabili che costituiscono l'argomento delle funzioni vengono inizializzate con il valore degli argomenti passati, nel loro ordine; nel caso ci fosse discordanza tra il tipo di una variabile argomento e il tipo della variabile (o della costante letterale) passata, il compilatore cerca di effettuare una conversione implicita; nel caso non ci riesce si blocca e torna un errore. Si veda il seguente:

// ex4_5_1.cpp
#include <iostream.h>

double divisione (double dividendo, double divisore) {
  double quoziente = dividendo / divisore;
  return quoziente;
}

int divisione2 (int dividendo, int divisore) {
  int quoziente = dividendo / divisore;
  return quoziente;
}

double divisione3 (int dividendo, int divisore) {
  int quoziente = dividendo / divisore;
  return quoziente;     // conversione imp. int -> double  OK
}

int divisione4 (double dividendo, double divisore) {
  double quoziente = dividendo / divisore;
  return quoziente;     // conversione imp. double -> int
                        // il compilatore torna un WARNING
}

void main() {
  int a = 10, b = 4;
  double x = 2.71, y = 2.0;
  cout << divisione  (a, b) << "\t"; // conversione int -> double
  cout << divisione2 (a, b) << "\t"; // tutto OK
  cout << divisione3 (a, b) << "\t"; // argomenti OK
  cout << divisione4 (a, b) << "\n"; // conversione int -> double
  cout << divisione  (x, y) << "\t"; // tutto OK
  cout << divisione2 (x, y) << "\t"; // conversione double -> int
  // messaggio di WARNING dal compilatore
  cout << divisione3 (x, y) << "\t"; // conversione double -> int
  // messaggio di WARNING dal compilatore
  cout << divisione4 (x, y)        ; // argomenti OK
}

output:
 2.5 2 5 2
 1.355 1 1 1

Provando ad eseguire il programma ci vengono segnalati dei messaggi di warning in relazione alle righe di codice segnalate tramite commenti; il motivo risiede nel fatto che convertendo implicitamente un double in un int si perde della informazione, nel caso specifico la parte decimale. Si faccia dunque bene attenzione ad usare per le funzioni il giusto tipo, negli argomenti e nel ritorno, per evitare brutte sorprese.

Abbiamo notato che la programmazione modulare (utilizzando le funzioni) porta dei considerevoli vantaggi; la domanda che possiamo porci a questo punto è: quanto dobbiamo strutturare la nostra programmazione, ovvero quanto devono essere lunghe (in termini di righe di codice) le nostre funzioni? La risposta è semplice: strutturare al massimo ragionevole la nostra programmazione è nella maggior parte dei casi una ottima idea. In ogni modo, bisogna cercare di costruire delle funzioni che, al tempo stesso, siano di immediata visualizzazione (e quindi siano costituite da non troppe righe di codice, 20-30 per intenderci) eppure svolgano un compito completo. La motivazione è duplice: se una funzione svolgesse troppi compiti contemporaneamente sarebbe difficile da riutilizzare nello stesso programma, e d'altra parte se essa non svolgesse interamente un compito, avremmo bisogno sempre di più di una funzione per una sola operazione, il che è scomodo. Vediamo un esempio:


// ex4_5_2.cpp
#include <iostream.h>

// accelerazione di gravita' sulla superficie terrestre
const double g = 9.81;

double f (double t, double v0, double z0) {
  double z = z0 - v0 * t - .5 * g * t * t;
  return z;
}

double get_z0 () {
  double x;
  do {
    cout << "inserisci la distanza del "
      "corpo dal suolo\n\tz0 = ";
    cin >> x;
  } while (x <= 0);
  return x;
}

double get_v0 () {
  double x;
  do {
    cout << "inserisci la velocita' iniziale "
      "di caduta del corpo\n\tv0 = ";
    cin >> x;
  } while (x < 0);
  return x;
}

double get_step () {
  double x;
  do {
    cout << "inserisci l'intervallo di misurazione "
      "dei dati relativi alla caduta\n\tintervallo = ";
    cin >> x;
  } while (x <= 0);
  return x;
}

void traiettoria(double z0, double v0, double step) {
  cout << "\nTRAIETTORIA verticale\n";
  double z = z0;     // distanza iniziale dal suolo
  double t = 0;      // tempo all'istante 0
  while (z > 0) {    // si ferma quando il corpo atterra
    z = f(t, v0, z0);
    if (z >= 0)
      cout << "t = " << t << "\t\tz = " << z << "\n";
    else
      cout << "atterrato\n";
    t += step;       // aumenta il tempo
  }
}

void benvenuto () {
  cout << "Manuale di programmazione in C++\n"
    "per studenti delle scuole medie superiori\n\n"
    "questo programma calcola la traiettoria di un corpo\n"
    "in caduta libera fino all'atterraggio\n\n";
}

void main() {
  benvenuto();
  // distanza del corpo dal suolo
  double z0 = get_z0 ();
  // velocita' iniziale del corpo
  double v0 = get_v0 ();
  // intervallo di misurazione tempi
  double step = get_step ();
  // stampa la traiettoria verticale
  traiettoria (z0, v0, step);
}

esempio di output:
Manuale di programmazione in C++
per studenti delle scuole medie superiori

questo programma calcola la traiettoria di un corpo
in caduta libera fino all'atterraggio

inserisci la distanza del corpo dal suolo
z0 = 50
inserisci la velocita' iniziale di caduta del corpo
v0 = 1.5
inserisci l'intervallo di misurazione dei dati relativi alla caduta
intervallo = .2

TRAIETTORIA verticale
t = 0 z = 50
t = 0.2 z = 49.5038
t = 0.4 z = 48.6152
t = 0.6 z = 47.3342
t = 0.8 z = 45.6608
t = 1 z = 43.595
t = 1.2 z = 41.1368
t = 1.4 z = 38.2862
t = 1.6 z = 35.0432
t = 1.8 z = 31.4078
t = 2 z = 27.38
t = 2.2 z = 22.9598
t = 2.4 z = 18.1472
t = 2.6 z = 12.9422
t = 2.8 z = 7.3448
t = 3 z = 1.355
atterrato

Il precedente esempio calcola e stampa la traiettoria di un corpo in caduta libera, in prossimità della superficie terrestre; vale dunque la formula:

\begin{displaymath}
z = z_0 - v_0~t - \frac{1}{2}~g~t^2
\end{displaymath}

Si noti come, grazie all'utilizzo di diverse funzioni, il corpo principale del programma sia molto più leggibile di altri esempi già presentati. Nel caso commettessimo errori, inoltre, potremmo isolare le diverse funzioni e verificarle una ad una, senza dovere affrontare un lunghissimo programma unico.

ex-2
si scriva un programma che calcoli e stampi la traiettoria di un corpo che, oltre a essere in caduta libera, possiede una velocità uniforme orizzontale; si utilizzi la seguente formula:

\begin{displaymath}
\left\{ \begin{array}{l}
x = x_0 + v_{0x}~t \\
y = y_0 - v_{0y}~t - \frac{1}{2}~g~t^2
\end{array} \right.
\end{displaymath}

ove $x_0$, $y_0$, $v_{0x}$ e $v_{0y}$ siano immessi dall'utente, insieme all'intervallo di misurazione della traiettoria;
ex-3
si scriva un programma che calcoli il minore e il maggiore di tre numeri interi dati, utilizzando almeno due funzioni;


next up previous contents index
Next: Conversioni esplicite Up: Funzioni Previous: Funzioni in C++   Indice   Indice analitico
Claudio Cicconetti
2000-09-06