Strutture composte di strutture

Supponiamo di voler rappresentare in memoria delle figure geometriche più complesse del punto, per esempio dei segmenti. Un segmento lo possiamo considerare composto dai suoi due punti estremi. Potremmo quindi usare due variabili separate, ognuna della quali rappresenta un punto. Come si è detto, ogni volta che due o più variabili servono per rappresentare lo stesso oggetto, bisogna prendere in considerazione l'opportunità di definire una struttura in modo tale da poter usare un singola variabile composta di tipo struttura per rappresentare il singolo oggetto.

Nel nostro caso, un segmento è composto da due punti. Potremmo per esempio definire la struttura come composta da quattro valori reali. D'altra parte, il segmento è intuitivamente fatto di due punti, per cui il modo più naturale di definire la struttura è quelle di dire che è composta da due punti:

struct Segmento {
  TipoPunto primo;
  TipoPunto secondo;
};

typedef struct Segmento TipoSegmento;

Il punto importante di questo esempio è che un tipo definito usando struct oppure typedef è un tipo che ha esattamente tutte le caratteristiche di un tipo predefinito. Dal momento che possiamo usare un tipo predefinito per indicare il tipo di un campo di una struttura, ne segue che possiamo usare allo stesso scopo anche un tipo che abbiamo definito noi. Nel nostro caso, la definizione:

struct Abcd {
  int primo;
  int secondo;
};

è una definizione valida. Dal momento che TipoPunto è un tipo definito, possiamo usarlo anche al posto di int nella definizione di struttura di sopra. In questo modo, abbiamo capito che la definizione della struttura segmento è una definizione valida. Questo discorso serve solo a far capire che definire una struttura in cui uno o più campi sono di tipo struttura, è perfettamente valido.

Questa nuova struttura definita con campi struttura è ancora una struttura come tutte le altre, per cui si può definire un tipo a partire da esso, definire delle variabili di questo tipo, passare la struttura a una funzione, ecc.

Il programma che segue definisce il tipo segmento, definisce una funzione che decide se due segmenti si intersecano, dichiara due variabili di questo tipo, assegna ad esse dei valori, e poi chiama la procedura per vedere se i due segmenti si intersecano. L'unico punto da capire è: in che modo si accede alle coordinate dei punti estremi del segmento? Se s è una variabile di tipo segmento, allora è composta da due sottovariabili s.primo e s.secondo, che sono entrambe variabili di tipo punto. Dal momento che a.primo è di tipo punto, è composta da due campi, a cui si può accedere mettendo .x e .y dopo il nome della variabile. Quindi, le coordinate del primo punto s.primo sono s.primo.x e s.primo.y. La figura seguente visualizza questo concetto.

La seguente figura fornisce una rappresentazione grafica della memoria occupata da due variabili di tipo segmento s e r.

Il programma completo segmenti.c è riportato qui sotto.

/*
  Definizione del tipo punto,
funzione che calcola la distanza.
*/

#include<stdlib.h>
#include<math.h>


/* definizione della struttura e tipo per il punto */

struct Punto {
  float x;
  float y;
};

typedef struct Punto TipoPunto;


/* definizione di struttura e tipo per il segmento */

struct Segmento {
  TipoPunto primo;
  TipoPunto secondo;
};

typedef struct Segmento TipoSegmento;


/* distanza fra due punti */

float distanza(TipoPunto a, TipoPunto b) {
  float d;

  d = sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));

  return d;
}


/* intersezione fra le due rette di due segmenti */

TipoPunto intersezione(TipoSegmento m, TipoSegmento n) {
  TipoPunto r;
  float a1, b1, c1;
  float a2, b2, c2;

  return r;
}


/* verifica se due segmenti si intersecano */

int intersecano(TipoSegmento m, TipoSegmento n) {
  TipoPunto i;

  i=intersezione(m, n);

  if( i.x<=m.primo.x && i.x>=m.secondo.x &&
      i.y<=m.primo.y && i.y>=m.secondo.y )
    return 1;
  else
    return 0;
}


/* main */

int main() {
  TipoSegmento s, r;

		/* assegna valori al primo segmento */
  s.primo.x=12.1;
  s.primo.y=1.2;
  s.secondo.x=-12;
  s.secondo.y=-1.2;

		/* assegna valori al secondo segmento */
  r.primo.x=-1.2;
  r.primo.y=0.0;
  r.secondo.x=.9;
  r.secondo.y=-.5;

  return 0;
}