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

/* Lunghezza massima nome */
#define ML 100

/* non e'richiesto ordinamento ma solo che si possano gestire
 * un numero di elementi non predeterminato -> lista non ordinata */
struct nodo{
  char nome[ML];
  char qualifica;
  int inquadramento;
  struct nodo *prossimo;
};

/* prototipi funzioni */
void *Malloc(size_t); 
FILE *Fopen(const char *, const char *);
struct nodo *leggi_riga(FILE *);
struct nodo *inserisci_in_lista(struct nodo *, struct nodo *);
void stampa_qualifica(struct nodo *, char);
void stampa_inquadramento(struct nodo *, int);
void stampa_nodo(struct nodo*);

/* evito l'utilizzo di variabili globali */

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

 /* un puntatore per dati temporanei e uno per
  * la testa della lista */
 struct nodo *tmp;
 struct nodo *testa=NULL; /* lista inizialmente vuota */
 /* file handler per lettura */
 FILE *dati;
 /* stringa per gestire lettura da tastiera */
 char input[ML];
 char comando;

	
 /* PRIMA PARTE: leggo e interpreto il file */
 dati=Fopen("inquadr.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 nella lista */
  testa=inserisci_in_lista(testa, 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);
  /* considero solo il primo carattere*/
  comando=input[0];
  /* guardo se e'un carattere o una cifra,
   * isalpha e isdigit erano probabilmente soluzioni
   * piu'eleganti */
  if(('0'<=comando)&&(comando<='9'))
    stampa_inquadramento(testa, (int)(comando-'0'));
  else
    stampa_qualifica(testa, comando);
 }

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

/* questa funzione legge una riga del file e ritorna cio' che ha letto
 * 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));

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

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

 letto->prossimo=NULL;

 return letto;
}


/* questa funzione inserisce  i dati in una lista non
 * ordinata e restituisce la testa */

struct nodo *inserisci_in_lista(struct nodo *head, struct nodo *new){

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

 /* altrimenti ricorsivamente inserisco in una sottolista */
 head->prossimo=inserisci_in_lista(head->prossimo, new);
 return head;
}

/* le prossime due funzioni scandiscono la lista e confrontano
 * il secondo argomento con i dati per decidere se stampare o meno,
 * per semplicita' si sfrutta la ricorsione */

void stampa_inquadramento(struct nodo *head, int q){
  
  /* condizione di uscita */
  if(!head)return;

  if(head->inquadramento==q)
    stampa_nodo(head);

  /* passo all'elemento successivo */
  stampa_inquadramento(head->prossimo, q);
  return;
}

void stampa_qualifica(struct nodo *head, char q){
  
  /* condizione di uscita */
  if(!head)return;

  if(head->qualifica==q)
    stampa_nodo(head);

  /* passo all'elemento successivo */
  stampa_qualifica(head->prossimo, q);
  return;
}


/* semplice funzione per stampare i dati */
void stampa_nodo(struct nodo *a){
  /* controllo che ci sia qualcosa da stampare */
  if(!a)return;

  /* stampo ed esco */
  printf("%s -- %c%d\n", a->nome, a->qualifica, a->inquadramento);
}
/* 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;
}