INFORMATICA Il costrutto struct
Il costrutto struct Supponiamo di dover realizzare una base dati contenente i nomi e l’anno di   corso di una popolazione studentesca. Non si può ricorrere a una matrice bidimensionale con una dimensione per le variabili di tipo   carattere (per i nomi) e l'altra per la variabile intera (anno di corso): le matrici possono essere di dimensioni qualsiasi ma il  tipo-base  deve essere unico! Occorrerebbe definire una matrice (vettore di vettori)   di caratteri per i nomi e un vettore di interi per l'anno di corso: due   strutture dati separate tra loro. Pertanto l'allineamento dei dati inerenti la stessa persona dovrà essere garantito dal programmatore mediante una efficiente politica di gestione di indici.
Il costrutto struct La difficoltà è superata da un altro tipo di dato strutturato, molto più flessibile: il tipo  struct . Si tratta di una collezione di dati, anche di caratteristiche molto diverse tra loro (tipo diverso!), che però sono identificati dallo stesso nome.   Una struttura è formata da  membri  o  campi . Ogni campo rappresenta un dato (col suo tipo) della collezione . In questo modo dati di natura diversa (ovvero rappresentati in memoria da codici binari diversi) ma riferentesi alla stessa cosa, possono condividere lo stesso nome
Il costrutto struct Sono numerose le informazioni che intrinsecamente possono accordarsi con questo tipo di dato, ad esempio: una data è composta da  giorno  ( int ),  mese  ( char ) e  anno  ( int ) e quindi si può definire una struttura composta da questi tre campi; una persona è identificata da  nome ,  cognome ,  data di nascita ,  codice fiscale ,  stato civile ,  indirizzo , ecc., quindi si può definire una struttura composta da tutti questi campi; la classifica di una manifestazione sportiva è composta da  nome  e  cognome  degli atleti a cui è associata la  prestazione  (tempo impiegato, punti, ecc.).
Il costrutto struct Poiché in italiano il termine “ struttura  ” è usato con un'accezione più   generica, viene di solito utilizzata la dizione di   record , mutuata da altri linguaggi, e per i  membri  della struttura quella di  campi . I  campi  di un record possono essere di tipo diverso,  scalari ,  vettori  o, a loro volta, altre  struct .    Differentemente dai  vettori , i cui elementi sono identificati dal nome e dalla posizione occupata,   nelle  struct  i singoli elementi sono identificati dal nome della  struttura  e dal nome del  campo .  
Il costrutto struct Una  struct   viene definita elencando i nomi che si intendono attribuire ai singoli campi ( identificatori di campo ). Per ogni  identificatore di campo   poi, occorre specificare il tipo.  struct [ nome_struct  ]  { tipo_1 variabile_1;  /*  campo 1  */ tipo_2 variabile_2;  /*  campo 2  */ .......... tipo_n variabile_n;  /*  campo n  */ }  [variabile] [,variabile]....; dove le parti opzionali sono tra parentesi quadra. nome_struct  costituisce il  tag , cioè il nome che identifica quel particolare tipo di struttura in successive dichiarazioni di variabili.
Il costrutto struct: esempi definizione di una variabile di tipo  record   una_persona : struct  { char nome[20]; char cognome[20]; int giorno_nascita; int mese_nascita; int anno_nascita; float peso; int altezza; }  una_persona;
Il costrutto struct : esempi definizione di un record denominato  data  e di una variabile  day  di quel tipo: struct data  { int  giorno; enum {gennaio, febbraio, marzo, aprile, maggio, giugno, luglio, agosto, settembre, ottobre, novembre, dicembre} mese; int  anno; }; struct data day;
Il costrutto struct: esempi definizione di  numero complesso  dato come  x + iy , dove  x  e  y  sono numeri reali e  : vengono definiti la  struct  denominata  complesso  e la variabile  val_complex  di quel tipo  record . struct complesso  { double reale; double immaginario; }  val_complex;
Il costrutto struct Le variabili possono essere dichiarate nell’ambito della stessa struttura,   come succede per la variabile  val_complex , oppure esternamente come nel caso di  day :   ad esempio, dopo le dichiarazioni precedenti, sarebbero lecite le seguenti: struct  complesso  num_complesso; struct  data  giorno; I  campi  di una  struct  sono racchiusi in un blocco e quindi il loro campo di esistenza è limitato: è per questo che è lecita la definizione della variabile  giorno  nell’esempio precedente, pur esistendo un campo con lo stesso nome. Anche una funzione può essere definita di tipo  struct  e pertanto può restituire un valore di questo tipo.
La dichiarazione di una  struct  corrisponde alla creazione di un nuovo tipo. Pertanto (come per  enum ) si può rinominare questo tipo mediante il  typedef  per ottenere una struttura del programma più comprensibile e più leggibile. Esempio: #include <stdio.h> …………………… typedef struct  { double reale; double immaginario; }  complesso; main() { complesso  val_complex;  /* dichiarazione della variabile val_complex  */ ……………………………… .. Il costrutto struct creazione del nuovo tipo struct e ridefinizione del nome: il nuovo tipo si chiamerà  complesso .
Il costrutto struct Un  campo  di una  struct  può essere un  vettore , una  matrice  o un’altra  struct . Inoltre le  struct  possono costituire il tipo base per la definizione di  vettori .   Nel corso del programma si può far riferimento ad uno specifico  campo  di una  struct  indicando l'identificatore della variabile seguito da un punto e dal nome del  campo .    Il  campo  di una  struct  deve essere trattato come una qualsiasi altra variabile. Sul tipo  struct  nel suo complesso non agisce alcun   operatore, ma è lecita l'assegnazione di un’intera  struct  a un’altra  struct  dello stesso tipo.  I  campi  delle  struct  mantengono invece  le proprietà, e quindi gli operatori, del  tipo  a cui appartengono .
Il costrutto struct Esempio: /*  uso della struttura complesso  */ struct complesso { double reale; double immaginario; }; struct  complesso  x; .............. x.reale = 12.5; x.immaginario = 0.7;
struct: esempio Esempio: programma che riceve in input da tastiera delle  sequenze  di caratteri (parole) e calcola il numero di volte che è  presente ciascun carattere (frequenza statistica). La fine  dell'introduzione  delle parole sia  segnalata da  EOF  ( <CTRL>+Z ).  Il programma dovrà visualizzare tutti i caratteri diversi introdotti e la loro frequenza statistica.   La base dati può essere costituita da un  vettore di  struct  avente due campi: un campo carattere, di tipo  char , e un campo  presenze , di tipo  int .   Per ogni carattere letto da tastiera, si controlla se è già  presente:  s e presente, si incrementa il campo  presenze  di quel  carattere,  altrimenti lo  si  memorizza nel  campo  carattere  e si pone il valore 1 nel campo  presenze .
struct: esempio #include <stdio.h> #define NUM_MAX_CAR 100 typedef enum {FALSO, VERO} boolean; typedef struct { char carattere; int presenze; }  memoria; main() { int indice, num_car_pres; memoria  vett_car[NUM_MAX_CAR];  /*  vettore di strutture  */ int carat; boolean trovato;
struct: esempio num_car_pres = 0; printf (“\nIntroduci le sequenze di caratteri.\n &quot;); printf (&quot; Usa <CR> per andare a capo e <EOF> per finire:\n&quot;); while ((( carat = getchar()) != EOF)   && (num_car_pres < NUM_MAX_CAR)) /*  finché non si arriva a EOF  */ { if (carat != '\n') {  /* carat è diverso da new-line */ /*  cerca nella struct memoria se il carattere è già presente  */ trovato = FALSO; indice = 0;
struct: esempio while ((!trovato)  && (indice < num_car_pres)) if (vett_car[indice].carattere == carat) {  /*  il carattere introdotto esiste già  */  trovato = VERO; vett_car[indice].presenze++;  /* incr. campo presenze */ } else indice++;  /*  increm. indice  per scansione  */ if (!trovato) {  /* il carattere non c’è ancora nel vettore di struct: lo inserisce */ vett_car[num_car_pres].carattere = carat; vett_car[num_car_pres].presenze =   1; num_car_pres++;  /* incr. numero di caratteri inseriti nella struct*/ }  /* if not trovato  */ }  /*  if not eoln  */ }  /*  while not eof...  */
struct: esempio /*  stampa i risultati  */   printf (“\nCarattere  Presenze\n&quot;); for (indice = 0; indice < num_car_pres; indice++) { printf (&quot;  %c  &quot;, vett_car[indice].carattere); printf (&quot;%6d\n&quot;, vett_car[indice].presenze); } }
struct come parametro di funzioni Le  struct  si comportano a tutti gli effetti come variabili di tipo semplice, con la particolarità che possono essere viste sia come un insieme aggregato, ad esempio nell'assegnazione di un record ad un altro, sia come singoli elementi ( campi ).    In quest'ultimo caso, l'identificatore dell'elemento  è  costituito dal nome dell'intera struttura seguito dal punto e dal nome   del  campo  stesso.    Anche una funzione può essere definita di tipo  struct  e pertanto può restituire un valore di questo tipo.
struct come parametro di funzioni Esempio:  somma di due numeri complessi. #include <stdio.h> #include <math.h>   typedef  struct  { double reale; double immagin; }  complesso ; /* prototipo della funzione per la somma dei due numeri complessi */ complesso somma_cmplx (complesso dato1,   complesso dato2);  
struct come parametro di funzioni main() { complesso x, y, total; printf (“\nParte reale di x = &quot;); scanf (&quot;%lf&quot;, &x.reale); printf (“\nparte immaginaria di x = &quot;); scanf (&quot;%lf&quot;, &x.immagin); printf (“\nParte reale di y = &quot;); scanf (&quot;%lf&quot;, &y.reale); printf (“\nparte immaginaria di y = &quot;); scanf (&quot;%lf&quot;, &y.immagin); total = somma_cmplx (x, y); printf (“\nLa somma vale: %f&quot;, total.reale);  /* stampa della parte intera */ if (total.immagin < 0.0) printf(&quot; - i&quot;);  /*  stampa l’operatore i  */ else printf(&quot; + i&quot;); printf (&quot;%f&quot;,  fabs(total.immagin));  /* stampa parte immaginaria */ }
struct come parametro di funzioni complesso somma_cmplx (complesso dato1, complesso dato2)  { complesso somma; somma.reale = dato1.reale + dato2.reale; somma.immagin = dato1.immagin + dato2.immagin; return (somma); }
struct come parametro di funzioni Osservazioni:   nel programma principale, i dati di tipo  struct  vengono usati come parametri di  scanf  e  printf  con le stesse modalità delle variabili di tipo semplice; nella chiamata della funzione di tipo complesso  somma_cmplx ,  i  dati di tipo  struct   vengono passati  by value  : pertanto quando il controllo dell'esecuzione è   passato alla funzione, verrà effettuata una copia delle variabili esterne   nelle variabili locali della funzione  dato1  e  dato2 ; la funzione è definita di tipo  struct  e restituisce un valore di tipo  struct , il quale viene assegnato alla variabile  total ; mediante  typedef  si è ridefinito il nome della  struct , semplificando l'intestazione della funzione.
Esempio: punti nel piano In un file,  il cui nome va richiesto da tastiera, ci sono le coordinate X e Y di una serie di punti appartenenti a un piano cartesiano. Non si conosce a priori il numero di punti: si supponga siano meno di 100.   Leggere il file, calcolare la distanza dall'origine di ogni singolo punto, quindi riordinare i punti rispetto alla distanza dall'origine (dal più vicino al più lontano). Infine visualizzarli su monitor e salvarli (un punto per riga) in un file il cui nome va anch’esso richiesto da tastiera.
Esempio: punti nel piano Ad esempio se il file dei punti si chiama PUNTI.DAT e contiene: 2 2 1 4 3 3 0 1 sul monitor dovrà apparire: Punto  1:  0.0000,  1.0000  ->  1.0000 Punto  2:  2.0000,  2.0000  ->  2.8284 Punto  3:  1.0000,  4.0000  ->  4.1231 Punto  4:  3.0000,  3.0000  ->  4.2426
Esempio: punti nel piano #include <stdio.h> #include <math.h> #define NMAX 100 typedef enum {FALSO, VERO} boolean;  /*  “tipo” boolean  */   typedef struct  /*  “tipo”  modello  */ { double x; double y; double dist; }  modello; /*  prototipo della funzione di riordinamento  */ void bubble (modello punti[ ], int n)
Esempio: punti nel piano main() { FILE *input, *output; int i, j, stato, np; char buffer[80], nomefile[20]; modello punti[NMAX];  /*  vettore di strutture  */   /*  Legge il nome del file  */ printf (“\nNome del file che contiene i punti:  &quot;); scanf (&quot;%s&quot;, nomefile); /*  Apre il file in lettura  */ if ((input = fopen (nomefile,&quot;r&quot;)) == NULL) { printf (&quot;\nErrore apertura file %s&quot;, nomefile); exit (0); }
Esempio: punti nel piano np = 0; while (fscanf (input, &quot;%lf%lf&quot;, &punti[np].x,   &punti[np].y) != EOF) { punti[np].dist = sqrt (punti[np].x * punti[np].x  + punti[np].y *  punti[np].y); np++; } fclose (input); bubble (punti, np);
Esempio: punti nel piano /*  Operazioni finali: chiede il nome del file di output e lo crea  */ printf (“\nNome del file di output:  &quot;);  scanf (&quot;%s&quot;, nomefile); if ((output = fopen (nomefile, “w&quot;)) == NULL)  { printf (&quot;\nErrore creazione file %s&quot;, nomefile); exit (1);  } /*  visualizza la sequenza di punti sul monitor e la salva nel file */ for (i = 0; i < np; i++) { printf (“\nPunto %3d: %9.4lf,%9.4lf %10.4lf&quot;, i+1,  punti[i].x,  punti[i].y,  punti[i].dist); fprintf (output, “\nPunto %3d: %9.4lf,%9.4lf %10.4lf&quot;, i+1,  punti[i].x,  punti[i].y,  punti[i].dist); } }
Esempio: punti nel piano void bubble (modello punti[ ], int n) {  modello provv;  /*  struttura!  */ int ind;  boolean ord; ord = FALSO; while (!ord)  { ord = VERO; for (ind = 0; ind < n-1; ind++) if (punti[ind].dist > punti[ind+1].dist)   { provv = punti[ind];   punti[ind] = punti[ind+1];   punti[ind+1] = provv;   ord = FALSO;   } } }

12 Struct

  • 1.
  • 2.
    Il costrutto structSupponiamo di dover realizzare una base dati contenente i nomi e l’anno di corso di una popolazione studentesca. Non si può ricorrere a una matrice bidimensionale con una dimensione per le variabili di tipo carattere (per i nomi) e l'altra per la variabile intera (anno di corso): le matrici possono essere di dimensioni qualsiasi ma il tipo-base deve essere unico! Occorrerebbe definire una matrice (vettore di vettori) di caratteri per i nomi e un vettore di interi per l'anno di corso: due strutture dati separate tra loro. Pertanto l'allineamento dei dati inerenti la stessa persona dovrà essere garantito dal programmatore mediante una efficiente politica di gestione di indici.
  • 3.
    Il costrutto structLa difficoltà è superata da un altro tipo di dato strutturato, molto più flessibile: il tipo struct . Si tratta di una collezione di dati, anche di caratteristiche molto diverse tra loro (tipo diverso!), che però sono identificati dallo stesso nome.   Una struttura è formata da membri o campi . Ogni campo rappresenta un dato (col suo tipo) della collezione . In questo modo dati di natura diversa (ovvero rappresentati in memoria da codici binari diversi) ma riferentesi alla stessa cosa, possono condividere lo stesso nome
  • 4.
    Il costrutto structSono numerose le informazioni che intrinsecamente possono accordarsi con questo tipo di dato, ad esempio: una data è composta da giorno ( int ), mese ( char ) e anno ( int ) e quindi si può definire una struttura composta da questi tre campi; una persona è identificata da nome , cognome , data di nascita , codice fiscale , stato civile , indirizzo , ecc., quindi si può definire una struttura composta da tutti questi campi; la classifica di una manifestazione sportiva è composta da nome e cognome degli atleti a cui è associata la prestazione (tempo impiegato, punti, ecc.).
  • 5.
    Il costrutto structPoiché in italiano il termine “ struttura ” è usato con un'accezione più generica, viene di solito utilizzata la dizione di record , mutuata da altri linguaggi, e per i membri della struttura quella di campi . I campi di un record possono essere di tipo diverso, scalari , vettori o, a loro volta, altre struct .   Differentemente dai vettori , i cui elementi sono identificati dal nome e dalla posizione occupata, nelle struct i singoli elementi sono identificati dal nome della struttura e dal nome del campo .  
  • 6.
    Il costrutto structUna struct viene definita elencando i nomi che si intendono attribuire ai singoli campi ( identificatori di campo ). Per ogni identificatore di campo poi, occorre specificare il tipo. struct [ nome_struct ] { tipo_1 variabile_1; /* campo 1 */ tipo_2 variabile_2; /* campo 2 */ .......... tipo_n variabile_n; /* campo n */ } [variabile] [,variabile]....; dove le parti opzionali sono tra parentesi quadra. nome_struct costituisce il tag , cioè il nome che identifica quel particolare tipo di struttura in successive dichiarazioni di variabili.
  • 7.
    Il costrutto struct:esempi definizione di una variabile di tipo record una_persona : struct { char nome[20]; char cognome[20]; int giorno_nascita; int mese_nascita; int anno_nascita; float peso; int altezza; } una_persona;
  • 8.
    Il costrutto struct: esempi definizione di un record denominato data e di una variabile day di quel tipo: struct data { int giorno; enum {gennaio, febbraio, marzo, aprile, maggio, giugno, luglio, agosto, settembre, ottobre, novembre, dicembre} mese; int anno; }; struct data day;
  • 9.
    Il costrutto struct:esempi definizione di numero complesso dato come x + iy , dove x e y sono numeri reali e : vengono definiti la struct denominata complesso e la variabile val_complex di quel tipo record . struct complesso { double reale; double immaginario; } val_complex;
  • 10.
    Il costrutto structLe variabili possono essere dichiarate nell’ambito della stessa struttura, come succede per la variabile val_complex , oppure esternamente come nel caso di day : ad esempio, dopo le dichiarazioni precedenti, sarebbero lecite le seguenti: struct complesso num_complesso; struct data giorno; I campi di una struct sono racchiusi in un blocco e quindi il loro campo di esistenza è limitato: è per questo che è lecita la definizione della variabile giorno nell’esempio precedente, pur esistendo un campo con lo stesso nome. Anche una funzione può essere definita di tipo struct e pertanto può restituire un valore di questo tipo.
  • 11.
    La dichiarazione diuna struct corrisponde alla creazione di un nuovo tipo. Pertanto (come per enum ) si può rinominare questo tipo mediante il typedef per ottenere una struttura del programma più comprensibile e più leggibile. Esempio: #include <stdio.h> …………………… typedef struct { double reale; double immaginario; } complesso; main() { complesso val_complex; /* dichiarazione della variabile val_complex */ ……………………………… .. Il costrutto struct creazione del nuovo tipo struct e ridefinizione del nome: il nuovo tipo si chiamerà complesso .
  • 12.
    Il costrutto structUn campo di una struct può essere un vettore , una matrice o un’altra struct . Inoltre le struct possono costituire il tipo base per la definizione di vettori .   Nel corso del programma si può far riferimento ad uno specifico campo di una struct indicando l'identificatore della variabile seguito da un punto e dal nome del campo .   Il campo di una struct deve essere trattato come una qualsiasi altra variabile. Sul tipo struct nel suo complesso non agisce alcun operatore, ma è lecita l'assegnazione di un’intera struct a un’altra struct dello stesso tipo. I campi delle struct mantengono invece le proprietà, e quindi gli operatori, del tipo a cui appartengono .
  • 13.
    Il costrutto structEsempio: /* uso della struttura complesso */ struct complesso { double reale; double immaginario; }; struct complesso x; .............. x.reale = 12.5; x.immaginario = 0.7;
  • 14.
    struct: esempio Esempio:programma che riceve in input da tastiera delle sequenze di caratteri (parole) e calcola il numero di volte che è presente ciascun carattere (frequenza statistica). La fine dell'introduzione delle parole sia segnalata da EOF ( <CTRL>+Z ). Il programma dovrà visualizzare tutti i caratteri diversi introdotti e la loro frequenza statistica.   La base dati può essere costituita da un vettore di struct avente due campi: un campo carattere, di tipo char , e un campo presenze , di tipo int .   Per ogni carattere letto da tastiera, si controlla se è già presente: s e presente, si incrementa il campo presenze di quel carattere, altrimenti lo si memorizza nel campo carattere e si pone il valore 1 nel campo presenze .
  • 15.
    struct: esempio #include<stdio.h> #define NUM_MAX_CAR 100 typedef enum {FALSO, VERO} boolean; typedef struct { char carattere; int presenze; } memoria; main() { int indice, num_car_pres; memoria vett_car[NUM_MAX_CAR]; /* vettore di strutture */ int carat; boolean trovato;
  • 16.
    struct: esempio num_car_pres= 0; printf (“\nIntroduci le sequenze di caratteri.\n &quot;); printf (&quot; Usa <CR> per andare a capo e <EOF> per finire:\n&quot;); while ((( carat = getchar()) != EOF) && (num_car_pres < NUM_MAX_CAR)) /* finché non si arriva a EOF */ { if (carat != '\n') { /* carat è diverso da new-line */ /* cerca nella struct memoria se il carattere è già presente */ trovato = FALSO; indice = 0;
  • 17.
    struct: esempio while((!trovato) && (indice < num_car_pres)) if (vett_car[indice].carattere == carat) { /* il carattere introdotto esiste già */ trovato = VERO; vett_car[indice].presenze++; /* incr. campo presenze */ } else indice++; /* increm. indice per scansione */ if (!trovato) { /* il carattere non c’è ancora nel vettore di struct: lo inserisce */ vett_car[num_car_pres].carattere = carat; vett_car[num_car_pres].presenze = 1; num_car_pres++; /* incr. numero di caratteri inseriti nella struct*/ } /* if not trovato */ } /* if not eoln */ } /* while not eof... */
  • 18.
    struct: esempio /* stampa i risultati */   printf (“\nCarattere Presenze\n&quot;); for (indice = 0; indice < num_car_pres; indice++) { printf (&quot; %c &quot;, vett_car[indice].carattere); printf (&quot;%6d\n&quot;, vett_car[indice].presenze); } }
  • 19.
    struct come parametrodi funzioni Le struct si comportano a tutti gli effetti come variabili di tipo semplice, con la particolarità che possono essere viste sia come un insieme aggregato, ad esempio nell'assegnazione di un record ad un altro, sia come singoli elementi ( campi ).   In quest'ultimo caso, l'identificatore dell'elemento è costituito dal nome dell'intera struttura seguito dal punto e dal nome del campo stesso.   Anche una funzione può essere definita di tipo struct e pertanto può restituire un valore di questo tipo.
  • 20.
    struct come parametrodi funzioni Esempio: somma di due numeri complessi. #include <stdio.h> #include <math.h>   typedef struct { double reale; double immagin; } complesso ; /* prototipo della funzione per la somma dei due numeri complessi */ complesso somma_cmplx (complesso dato1, complesso dato2);  
  • 21.
    struct come parametrodi funzioni main() { complesso x, y, total; printf (“\nParte reale di x = &quot;); scanf (&quot;%lf&quot;, &x.reale); printf (“\nparte immaginaria di x = &quot;); scanf (&quot;%lf&quot;, &x.immagin); printf (“\nParte reale di y = &quot;); scanf (&quot;%lf&quot;, &y.reale); printf (“\nparte immaginaria di y = &quot;); scanf (&quot;%lf&quot;, &y.immagin); total = somma_cmplx (x, y); printf (“\nLa somma vale: %f&quot;, total.reale); /* stampa della parte intera */ if (total.immagin < 0.0) printf(&quot; - i&quot;); /* stampa l’operatore i */ else printf(&quot; + i&quot;); printf (&quot;%f&quot;, fabs(total.immagin)); /* stampa parte immaginaria */ }
  • 22.
    struct come parametrodi funzioni complesso somma_cmplx (complesso dato1, complesso dato2) { complesso somma; somma.reale = dato1.reale + dato2.reale; somma.immagin = dato1.immagin + dato2.immagin; return (somma); }
  • 23.
    struct come parametrodi funzioni Osservazioni:   nel programma principale, i dati di tipo struct vengono usati come parametri di scanf e printf con le stesse modalità delle variabili di tipo semplice; nella chiamata della funzione di tipo complesso somma_cmplx , i dati di tipo struct vengono passati by value : pertanto quando il controllo dell'esecuzione è passato alla funzione, verrà effettuata una copia delle variabili esterne nelle variabili locali della funzione dato1 e dato2 ; la funzione è definita di tipo struct e restituisce un valore di tipo struct , il quale viene assegnato alla variabile total ; mediante typedef si è ridefinito il nome della struct , semplificando l'intestazione della funzione.
  • 24.
    Esempio: punti nelpiano In un file, il cui nome va richiesto da tastiera, ci sono le coordinate X e Y di una serie di punti appartenenti a un piano cartesiano. Non si conosce a priori il numero di punti: si supponga siano meno di 100.   Leggere il file, calcolare la distanza dall'origine di ogni singolo punto, quindi riordinare i punti rispetto alla distanza dall'origine (dal più vicino al più lontano). Infine visualizzarli su monitor e salvarli (un punto per riga) in un file il cui nome va anch’esso richiesto da tastiera.
  • 25.
    Esempio: punti nelpiano Ad esempio se il file dei punti si chiama PUNTI.DAT e contiene: 2 2 1 4 3 3 0 1 sul monitor dovrà apparire: Punto 1: 0.0000, 1.0000 -> 1.0000 Punto 2: 2.0000, 2.0000 -> 2.8284 Punto 3: 1.0000, 4.0000 -> 4.1231 Punto 4: 3.0000, 3.0000 -> 4.2426
  • 26.
    Esempio: punti nelpiano #include <stdio.h> #include <math.h> #define NMAX 100 typedef enum {FALSO, VERO} boolean; /* “tipo” boolean */   typedef struct /* “tipo” modello */ { double x; double y; double dist; } modello; /* prototipo della funzione di riordinamento */ void bubble (modello punti[ ], int n)
  • 27.
    Esempio: punti nelpiano main() { FILE *input, *output; int i, j, stato, np; char buffer[80], nomefile[20]; modello punti[NMAX]; /* vettore di strutture */   /* Legge il nome del file */ printf (“\nNome del file che contiene i punti: &quot;); scanf (&quot;%s&quot;, nomefile); /* Apre il file in lettura */ if ((input = fopen (nomefile,&quot;r&quot;)) == NULL) { printf (&quot;\nErrore apertura file %s&quot;, nomefile); exit (0); }
  • 28.
    Esempio: punti nelpiano np = 0; while (fscanf (input, &quot;%lf%lf&quot;, &punti[np].x, &punti[np].y) != EOF) { punti[np].dist = sqrt (punti[np].x * punti[np].x + punti[np].y * punti[np].y); np++; } fclose (input); bubble (punti, np);
  • 29.
    Esempio: punti nelpiano /* Operazioni finali: chiede il nome del file di output e lo crea */ printf (“\nNome del file di output: &quot;); scanf (&quot;%s&quot;, nomefile); if ((output = fopen (nomefile, “w&quot;)) == NULL) { printf (&quot;\nErrore creazione file %s&quot;, nomefile); exit (1); } /* visualizza la sequenza di punti sul monitor e la salva nel file */ for (i = 0; i < np; i++) { printf (“\nPunto %3d: %9.4lf,%9.4lf %10.4lf&quot;, i+1, punti[i].x, punti[i].y, punti[i].dist); fprintf (output, “\nPunto %3d: %9.4lf,%9.4lf %10.4lf&quot;, i+1, punti[i].x, punti[i].y, punti[i].dist); } }
  • 30.
    Esempio: punti nelpiano void bubble (modello punti[ ], int n) { modello provv; /* struttura! */ int ind; boolean ord; ord = FALSO; while (!ord) { ord = VERO; for (ind = 0; ind < n-1; ind++) if (punti[ind].dist > punti[ind+1].dist) { provv = punti[ind]; punti[ind] = punti[ind+1]; punti[ind+1] = provv; ord = FALSO; } } }