/* possibile soluzione all'esame del 24.11.2000*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>

/* Lunghezza nome */
#define ML 100

/* nodo dell'albero binario di ricerca */
struct nodo{
  char nome[ML];
  unsigned int interno; /* su turbo C e' sufficiente */
  unsigned int ufficio; 
  struct nodo *maggiori, *minori;
};

/* prototipi funzioni */
void *Malloc(size_t); 
FILE *Fopen(const char *, const char *);
struct nodo *leggi_riga(FILE *);
struct nodo *inserisci_in_albero(struct nodo *, struct nodo *);
void stampa_ufficio(struct nodo *, int);
struct nodo *ricerca(struct nodo*, int);

/* evito l'utilizzo di variabili globali */

int main(int argc, char **argv){

 /* un puntatore per dati temporanei e uno per
  * la radice dell'albero */
 struct nodo *tmp;
 struct nodo *albero=NULL; /* il mio albero binario di ricerca */
 /* file handler per lettura */
 FILE *dati;
 /* stringa e intero per lettura da tastiera */
 char input[ML];
 int cosafare;

	
 /* PRIMA PARTE: leggo e interpreto il file */
 dati=Fopen("interni.txt","r");

 while(1){

  /* leggo una singola riga
   * se non riesco la funzione restituisce NULL
   * e lo interpreto come fine file ed esco */
  tmp=leggi_riga(dati);
  if(!tmp)break;

  /* inserisco i dati nell'albero binario */
  albero=inserisci_in_albero(albero, tmp);
 }

 /* SECONDA PARTE: iterativamente chiedo un tasto
  * ed eseguo l'operazione relativa */
 while(1){
  printf("Inserisci un comando: ");
  /* leggo il comando */
  fgets(input,ML,stdin);
  /* lo converto in numero */
  cosafare=atoi(input);
  /* cerco di capire se e' composto da una cifra
   * o piu` */
  if(cosafare>10){
    tmp=ricerca(albero, cosafare);
    /* se tmp e' diverso da NULL allora lo stampo */
    if (tmp) {
      printf("%s - %d\n", tmp->nome, tmp->interno);
    }
  }
  else
    stampa_ufficio(albero,cosafare);

 }

 return EXIT_SUCCESS; /* codice di uscita senza errori */
}

/* questa funzione legge descrizione del bene e relativo prezzo se
 * non riesce a leggere ritorna NULL */
struct nodo *leggi_riga(FILE *a){
 struct nodo *letto;
 int nb;

 /* alloco struttura per dati */
 letto=Malloc(sizeof(struct nodo));
 letto->maggiori=letto->minori=NULL;

 /* provo a leggere dal file i tre elementi che compongono la riga*/
 nb=fscanf(a, "%d;%d;%[^\n]\n",&letto->ufficio,&letto->interno,letto->nome);

 /* se e' riuscito a leggere una riga completa nb deve essere
  * pari ad tre (numero dei componenti) */
 if(nb!=3){
  free(letto);
  return NULL;
 }

 return letto;
}


/* questa funzione inserisce  i dati in un albero binario  e restituisce la
 * radice, il codice ISBN e' usato come chiave */

struct nodo *inserisci_in_albero(struct nodo *tree, struct nodo *new){

 /* se l'albero non esiste il primo nodo e'
  * sicuramente la radice */
 if(!tree)return new;

 if(tree->interno<new->interno)
   tree->maggiori=inserisci_in_albero(tree->maggiori, new);
 }else
   tree->minori=inserisci_in_albero(tree->minori, new);
 }

 return tree;
}

/* questa procedura ricerca nell'albero binario l`interno
 * ne restituisce il puntatore oppure NULL */
struct nodo *ricerca(struct nodo *a, int c){

 /* se il sottoalbero di ricerca non esiste ritorno
  * NULL (non ho trovato l'interno) */ 
 if(!a)return NULL;

 /* a seconda del risultato ho trovato la chiave o
  * devo continuare la ricerca */
 if(a->interno==c) return a;
 if(a->interno<c) return ricerca(a->maggiori, c);
 return ricerca(a->minori, c);
}

/* E' un semplice attraversamento con verifica corrispondenza
 * ufficio con quello da stampare */
void stampa_ufficio(struct nodo *a, int uff){
  if(!a)return;
  stampa_ufficio(a->maggiori, uff);
  if(a->ufficio==uff) printf("%s - %d\n", a->nome, a->interno);
  stampa_ufficio(a->minori, uff);
}

/* solite procedure utilizzate durante il corso */
/*************************************************************************/

void *Malloc(size_t size)
{
 void *genericp;
 if((genericp=malloc(size))==NULL)
  {
   perror("Malloc");
   exit(1);
  }
  return genericp;
}

/*************************************************************************/

FILE *Fopen(const char *nome, const char *modo)
{
FILE *tmp;

 if((tmp=fopen(nome, modo))==NULL)
  {
   fprintf(stderr, "Non riesco ad aprire il file %s in maniera %s\n",nome, modo);
   perror("Fopen");
   exit(1);
  }
 return tmp;
}