#include<stdio.h>
#include<stdlib.h>
#include<string.h>


#define MAX_CHAR_STAZ 33 /* numero caratteri
			  * massimo per stazione 
			  * piu'uno per fine stringa */

/* struttura contenente le stazioni,
 * scelgo una lista singolarmente concatenata */
struct stazione{
  unsigned int distanza;
  unsigned int costo_per_km;
  char nome[MAX_CHAR_STAZ];
  struct stazione *prossimo;
};

/* prototipi */
void aggiungi_stazione(struct stazione*, struct stazione*);
struct stazione *cerca_stazione(struct stazione*, char *);
int calcola_costo(struct stazione*, struct stazione*);
void *Malloc(size_t); 
FILE *Fopen(const char *, const char *);


int main(int argc, char **argv)
{
FILE *mystream;
struct stazione *tmp;
struct stazione *tratta;
int numdati;
char stazione1[MAX_CHAR_STAZ], stazione2[MAX_CHAR_STAZ];
struct stazione *p1, *p2;
int costo_totale;

 /* PRIMA PARTE: LEGGO E MEMORIZZO I DATI */

  /* apro il file */
  mystream=Fopen("STAZIONI.TXT", "r");


  printf("Sto leggendo i dati");
  tratta=NULL;
  while(!feof(mystream))
   {
    /* alloco un puntatore temporeaneo che serve per contenere i
     * dati via via che sono letti */
    tmp=Malloc(sizeof(struct stazione));
    tmp->prossimo=NULL;
    /* leggo la riga ed esco se non esiste */
    numdati=fscanf(mystream,"%d#%d#%[^\n]\n", &tmp->distanza, &tmp->costo_per_km, tmp->nome);
    /* se non vi sono errori nel file deve aver
     * letto 3 elementi */
    if(numdati!=3)break;
    printf(".");
    /* ora devo aggiungere la stazione alla lista
     * prima controllo se esiste la lista */
    if(!tratta){
      /* non esiste, quindi la stazione letta
       * diventa la testa della lista */
      tratta=tmp;
    }else{
      aggiungi_stazione(tratta, tmp);
    }
   }/*while*/
  printf("\n");

 /* SECONDA PARTE: CHIEDO DUE STAZIONI E CALCOLO LA DISTANZA */
  while(1){
    printf("Inserire nome prima stazione: ");
    fgets(stazione1, MAX_CHAR_STAZ, stdin);
    /* fgets inserisce un ``a capo'', lo 
     * limino */
    stazione1[strlen(stazione1)-1]='\0';
    p1=cerca_stazione(tratta, stazione1);
    if(!p1){
      fprintf(stderr, "Errore stazione non trovata!\n");
      continue;
    }
    printf("Inserire nome seconda stazione: ");
    fgets(stazione2, MAX_CHAR_STAZ, stdin);
    stazione2[strlen(stazione2)-1]='\0';
    p2=cerca_stazione(tratta, stazione2);
    if(!p2){
      fprintf(stderr, "Errore stazione non trovata!\n");
      continue;
    }
    if(p2==p1){
      fprintf(stderr, "Errore: inserire due stazioni differenti!\n");
      continue;
    }

    /* il calcolo della distanza e'semplice */
    printf("Distanza: %d\n", abs(p1->distanza-p2->distanza));
    /* per calcolare il costo totale occorre scorrere
     * la lista */
    /* il file e' ordinato in funzione della
     * distanza, cerco di capire in che ordine scorrere
     * la lista */
    if(p1->distanza>p2->distanza)
      costo_totale=calcola_costo(p2, p1);
    else
      costo_totale=calcola_costo(p1, p2);

    printf("Costo: %d\n", costo_totale);
  }/*while*/

}

/* cerca una stazione nella lista, ritorna l'indirizzo in memoria se la trova
 * oppure NULL in caso non la trovi */
struct stazione *cerca_stazione(struct stazione *lista, char *nome){

  /* scorro la lista fino a che non trovo il
   * nome di stazione che sto cercando o
   * fino a quando non sono a fine lista */
  for(;lista!=NULL;lista=lista->prossimo)
    if(!strcmp(nome, lista->nome))
	break;

  /* ritorno il valore trovato
   * oppure NULL */
  return lista;
}

/* aggiunge una stazione alla lista di stazioni semplicemente accodandola */
void aggiungi_stazione(struct stazione *lista, struct stazione *nuovo){

  /* scorro la lista fino al penultimo elemento */
  for(;lista->prossimo;lista=lista->prossimo);

  /* ora p punta all'ultimo elemento, a seguire aggiungo
   * la nuova stazione */
  lista->prossimo=nuovo;
}

/* questa procedura calcola il costo complessivo della
 * tratta. Attenzione: a deve essere prima di b nel file */
int calcola_costo(struct stazione *a, struct stazione *b){
  int costo=0;

  /* percorro la lista per calcolare il costo */
  for(;a!=b;a=a->prossimo)
	costo+=(a->prossimo->distanza-a->distanza)*a->costo_per_km;

  return costo;
}
/*************************************************************************/

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)
  {
   printf("Non riesco ad aprire il file %s in maniera %s\n",nome, modo);
   perror("Fopen");
   exit(1);
  }
return tmp;
}