Sezione 3.5
Strutture


Strutture dati.

Una struttura dati è un insieme di tipi diversi di dati raggruppati in un'unica dichiarazione. La forma della dichiarazione è la seguente:   
struct nome_modello {
  tipo1 nome_elemento1;
  tipo2 nome_elemento2;
  tipo3 nome_elemento3;
  .
  .
}
nome_oggetto;
in cui nome_modello è un nome per il modello di struttura e nome_oggetto (opzionale) è un identificatore che denota un oggetto avente la struttura nome_modello . Tra le parentesi graffe {} sono indicati i tipi e i rispettivi sub_identificatori degli elementi che compongono la struttura.      

Una volta dichiarata una struttura il suo nome può essere utilizzato come un nuovo tipo di dati. Ad esempio:

struct prodotti {
  char nome [30];
  float prezzo;
} ;

prodotti mele;
prodotti arance, meloni;
Abbiamo dapprima definito il modello di struttura prodotti con due campi: nome e prezzo, di tipi diversi. Abbiamo quindi usato il nome del modello di struttura ( prodotti ) per dichiarare tre oggetti di tale tipo: mele , arance e meloni

Una volta dichiarato, prodotti è diventato un nuovo nome di tipo al pari di quelli fondamentali come  int , char o short. Abbiamo quindi potuto successivamente dichiarare degli oggetti (variabili) di tale tipo.

Il campo opzionale nome_oggetto che compare alla fine della dichiarazione di una struttura serve a dichiarare direttamente oggetti di tale tipo. Ad esempio avremmo potuto scrivere:

struct prodotti {
  char nome [30];
  float prezzo;
} mele, arance, meloni;
In questo caso, in cui inseriamo direttamente nella dichiarazione della struttura la dichiarazione di tutti gli oggetti di tale tipo, il nome nome_modello   (prodotti nel nostro caso)  è opzionale. Se nome_modello viene omesso non possiamo però dichiarare in seguito altri oggetti dello stesso tipo.              

Occorre distinguere chiaramente tra i concetti di modello della struttura e di oggetto appartenente alla struttura. Facendo il parallelo con i termini che abbiamo usato per le variabili possiamo dire che il modello è il tipo e l'oggetto è la variabile. Si possono dichiarare molti oggetti (variabili) di uno stesso modello (tipo).

Una volta dichiarati i tre oggetti mele, arance e meloni possiamo operare sui campi che li costituiscono. Per fare questo bisogna usare un punto (.) tra il nome dell'oggetto ed il nome del campo. Ad esempio possiamo operare con le seguenti notazioni esattamente come fossero degli identificatori di variabile appartenenti ai rispettivi tipi:

mele.nome
mele.prezzo
arance.nome
arance.prezzo
meloni.nome
meloni.prezzo
ciascuna di esse appartiene al rispettivo tipo: mele.nome , arance.nome e meloni.nome sono di tipo char[30], mentre mele.prezzo , arance.prezzo e meloni.prezzo sono di tipo float.                  

Vediamo un altro esempio:

// esempio con le strutture
#include <iostream.h>
#include <string.h>
#include <stdlib.h>

struct film_t {
  char titolo [50];
  int anno;
} mio, tuo;

void stampaFilm (film_t film);

int main ()
{
  strcpy (mio.titolo, "2001 Odissea nello spazio");
  mio.anno = 1968;

  cout << "Dammi il titolo: ";
  cin.getline (tuo.titolo,50);
  cout << "Dammi l'anno: ";
  cin >> tuo.anno;

  cout << "Il mio film preferito e':\n ";
  stampaFilm (mio);
  cout << "Il tuo e':\n ";
  stampaFilm (tuo);
  return 0;
}

void stampaFilm (film_t film)
{
  cout << film.titolo;
  cout << " (" << film.anno << ")\n";
}
Dammi il titolo:  Alien
Dammi l'anno: 1979

Il mio film preferito e':
2001 Odissea nello spazio (1968)
Il tuo e':
 Alien (1979)

L'esempio mostra come si possano usare gli elementi di una struttura e la struttura stessa come fossero delle variabili. Ad esempio tuo.anno è una variabile di tipo int e mio.titolo è un array di 50 char

Osserviamo che sia mio che tuo sono usati come nomi di variabili di tipo film_t quando vengono passati come parametro alla funzione stampaFilm. Dunque uno dei principali vantaggi con le strutture è che si possono utilizzare sia i singoli campi individualmente sia la struttura completa come unico blocco.        

Le strutture si usano spesso per costruire basi di dati, specialmente considerando la possibilità di definire array di strutture.

// array di strutture
#include <iostream.h>
#include <stdlib.h>

#define N_FILM 5

struct film_t{
  char titolo [50];
  int anno;
} films [N_FILM];

void stampaFilm (film_t film);

int main ()
{
  int n;
  for (n=0; n<N_FILM; n++)
  {
    cout << "Dammi il titolo: ";
    cin.getline (films[n].titolo,50);
    cout << "Dammi l'anno: ";
    cin >> films[n].anno;
  }
  cout << "\nHai inserito i seguenti film:\n";
  for (n=0; n<N_MOVIES; n++)
    scriviFilm (films[n]);
  return 0;
}

void scriviFilm (film_t film)
{
  cout << film.titolo;
  cout << " (" << film.anno << ")\n";
}
Dammi il titolo:  Alien
Dammi l'anno: 1979
Dammi il titolo: Blade Runner
Dammi l'anno: 1982
Dammi il titolo:Matrix
Dammi l'anno: 1999
Dammi il titolo: Rear Window
Dammi l'anno: 1954
Dammi il titolo: Taxi Driver
Dammi l'anno: 1975

Hai inserito i seguenti film:
Alien (1979)
Blade Runner (1982)
Matrix (1999)
Rear Window (1954)
Taxi Driver (1975)

Strutture annidate

Le strutture si possono annidare in modo tale che un elemento di una struttura può essere a sua volta una struttura.  
struct film_t {
  char titolo [50];
  int anno;
}

struct amici_t {
  char nome [50];
  char email [50];
  film_t film_preferito;
  } carlo, maria;
Dopo tale dichiarazione possiamo usare le espressioni: 
carlo.nome
maria.film_preferito.titolo
carlo.film_preferito.anno






Precedente:
                                3-2. Stringhe di caratteri

index
Next:
3-6. Tipi definiti dall'utente.