next up previous contents index
Next: Stringhe di caratteri Up: Array, enumerati, stringhe Previous: Quick sort   Indice   Indice analitico

Enumerati

In questo paragrafo presenteremo il costrutto enum, il quale permette di creare nuovi tipi, detti enumerati. Abbiamo visto che ogni tipo in C++ ha degli insiemi di dati sui quali lavori; ecco una tabella riassuntiva sui tipi che abbiamo sino ad ora incontrato:
int numeri interi
unsigned int numeri interi positivi
double numeri reali
bool true,false
char caratteri
puntatori indirizzi di memoria
riferimenti oggetti esistenti
Grazie al costruttore di tipo enum possiamo avere a disposizione dei tipi del tutto nuovi, per i quali definiamo noi il dominio. Ad esempio potremo avere un nuovo tipo Colore, il quale permette di avere delle variabili i cui unici valori ammessi siano i colori:

// ex6_4_1
#include <iostream.h>

enum Colori { BIANCO, CIANO, ROSSO,
              MAGENTA, VERDE, GIALLO,
              BLU, NERO };

void main() {
  Colori c = VERDE;
  // Colori d = VIOLA;  // NO: VIOLA non appartiene
                        // al dominio di Colori
  cout << c;
}

output:
4

La sintassi di enum è molto semplice: basta inserire tra parentesi graffe per intero l'insieme di definizione delle variabili di tale tipo; in questa maniera possiamo creare, come nel nostro esempio, una variabile di tipo Colori, come se fosse un tipo primitivo, e inizializzarla o assegnarle uno dei valori ammessi. Cosa succede però quando andiamo a stampare la variabile c? Si ha che non viene stampato, come ci si potrebbe aspettare, la stringa di caratteri ``verde'', bensì il numero intero 4; il motivo risiede nel fatto che le variabili di tipi enumerati vengono trattate dal compilatore come numeri interi, e quindi stampate come tali: la numerazione parte da 0 per il primo dato dell'enumerato e prosegue incrementando sempre di una unità. Si noti che, per convenzione, gli elementi del dominio di un enumerato si scrivono interamente in caratteri masiuscoli. Se vogliamo che il nostro colore venga stampato, dobbiamo usare uno switch:


#include <iostream.h>

enum Colori { BIANCO, CIANO, ROSSO,
              MAGENTA, VERDE, GIALLO,
              BLU, NERO };

void main() {
  Colori colore;
  char c;
  bool ok;
  do {
    ok = true;
    cout << "colore (b,c,r,m,v,g,B,n)? "; cin >> c;
    switch (c) {
    case 'b': colore = BIANCO; break;
    case 'c': colore = CIANO; break;
    case 'r': colore = ROSSO; break;
    case 'm': colore = MAGENTA; break;
    case 'v': colore = VERDE; break;
    case 'g': colore = GIALLO; break;
    case 'B': colore = BLU; break;
    case 'n': colore = NERO; break;
    default: cout << "colore errato\n"; ok = false;
    }
  } while (!ok);
  cout << "hai scelto ";
  switch (colore) {
  case BIANCO: cout << "BIANCO"; break;
  case CIANO: cout << "CIANO"; break;
  case ROSSO: cout << "ROSSO"; break;
  case MAGENTA: cout << "MAGENTA"; break;
  case VERDE: cout << "VERDE"; break;
  case GIALLO: cout << "GIALLO"; break;
  case BLU: cout << "BLU"; break;
  case NERO: cout << "NERO"; break;
  }
}

esempio di output:
colore (b,c,r,m,v,g,B,n)? m
hai scelto MAGENTA

Le variabili dei tipi enumerati, come tutte le altre variabili, essere passate alle funzioni; vediamo un classico esempio:


// ex6_4_3
#include <iostream.h>

enum Giorni { LUN, MAR, MER,
              GIO, VEN, SAB, DOM };

void stampa (Giorni g) {
  switch (g) {
  case LUN: cout << "Lunedi'"; break;
  case MAR: cout << "Martedi'"; break;
  case MER: cout << "Mercoledi'"; break;
  case GIO: cout << "Giovedi'"; break;
  case VEN: cout << "Venerdi'"; break;
  case SAB: cout << "Sabato"; break;
  case DOM: cout << "Domenica";
  }
}

void main() {
  int g;
  cout << "giorno? "; cin >> g;
  g %= 7;
  stampa ((Giorni)g);
}

esempio di output: giorno? 4
Venerdi'

Osservazione fondamentale è che possiamo convertire senza problemi un intero in un giorno della settimana, perché, come abbiamo già rimarcato, il compilatore considera gli enum degli interi; se non effettuassimo la conversione esplicita nello statement stampa((Giorni)g), il risultato sarebbe lo stesso, ma probabilmente il compilatore tornerebbe un messaggio di warning. Si noti che, siccome i giorni della settimana una struttura modulare, cioè tornano sempre con la stessa sequenza dopo un periodo di 7 giorni, abbiamo preso (g %= 7) il modulo dell'intero immesso dall'utente. Grazie a questo semplice espediente, siamo in grado di stabilire che giorno della settimana sarà tra $n$ giorni, supponendo che la data odierna cada di lunedì . Un altro esempio di output è allora il seguente:
giorno? 7544
Sabato

La numerazione automatica degli enumerati può essere modificata dal programmatore in maniera molto semplice: assegnando ad ogni valore dell'enumerato l'intero che si vuole esso rappresenti; i valori che non vengono assegnati, continuano la normale enumerazione:


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

enum Enumerato { A = 5, B = 7,
                 C, D = 19, E, F };

void main() {
  cout << A << "\t" << B << "\n" <<
    C << "\t" << D << "\n" <<
    E << "\t" << F << "\n";
}

output:
 5 7      
 8 19      
 20 21      

Con questo termina la brevissima rassegna sui tipi enumerati; sarà dura trovare qualche semplice applicazione per tale costrutto, in quanto esso è diffuso maggiormente nelle librerie (elenchi di colori o eventi o simili). Grazie ad essi, il programmatore che usa una libreria grafica, ad esempio, non è costretto a ricordarsi che il colore ``rosso'' è identificato da un certo numero, ma gli è sufficiente utilizzare ``ROSSO'' ogni qual volta necessiti l'uso di tale colore. Se si ha già qualche esperienza di programmazione, sicuramente si è incontrato un costrutto simile; in caso contrario, ci cerchi di riconoscerlo una volta trovato per la prima volta.

ex-2
si scriva un programma che accetti un numero intero positivo, e stampi il corrispondente mese dell'anno; si crei e si utilizzi il tipo enumerato Mesi;


next up previous contents index
Next: Stringhe di caratteri Up: Array, enumerati, stringhe Previous: Quick sort   Indice   Indice analitico
Claudio Cicconetti
2000-09-06