/* possibile soluzione alla verifica del 31.5.2000 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/* lunghezza codice ISBN 10 caratteri +1 di fine stringa*/
#define LISBN 10+1
#define LBUFF 100
/* nodo dell'albero binario di ricerca */
struct nodo{
char isbn[LISBN];
char *titolo;
unsigned char scaffale;
struct nodo *maggiori, *minori;
};
/* prototipi funzioni */
void *Malloc(size_t);
FILE *Fopen(const char *, const char *);
void *Realloc(void *, size_t);
struct nodo *leggi_riga(FILE *);
struct nodo *inserisci_in_albero(struct nodo *, struct nodo *);
struct nodo *ricerca_libro(struct nodo *, char *);
int main(int argc, char **argv){
/* un puntatore per dati temporanei e uno per
* la radice dell'albero */
struct nodo *tmp;
struct nodo *albero_libri=NULL;
/* file handler per lettura */
FILE *dati;
/* codice ISBN da ricercare */
char code[LISBN];
/* puntatore a dati libri ricercati */
struct nodo *p;
/* PRIMA PARTE: leggo e interpreto libri.txt */
dati=Fopen("libri.txt","r");
while(1){
/* chiamo una funzione che legge una riga del file spezzandola in codice
* ISBN, titolo e scaffale. Questa funzione ritorna NULL qualora siamo a
* fondo file in questo caso esco dal ciclo */
tmp=leggi_riga(dati);
if(!tmp)break;
/* inserisco i dati nell'albero binario */
albero_libri=inserisci_in_albero(albero_libri, tmp);
}
/* SECONDA PARTE: iterativamente chiedo un codice ISBN
* e cerco e stampo lo scaffale relativo */
while(1){
printf("Inserisci un codice ISBN: ");
fgets(code, LISBN+1, stdin);
/* elimino l'invio */
code[LISBN-1]='\0';
printf("Sto ricercando %s\n", code);
p=ricerca_libro(albero_libri, code);
if(!p)
printf("Libro non presente !\n");
else
printf("Libro ``%s'' presente nello scaffale %d\n", p->titolo, (int)p->scaffale);
}
return EXIT_SUCCESS;
}
/* questa funzione legge codice ISBN, titolo e scaffale dal file passato se
* non riesce a leggere ritorna NULL */
struct nodo *leggi_riga(FILE *a){
struct nodo *letto;
int nb,np;
char c;
char *t;
/* alloco struttura per dati */
letto=Malloc(sizeof(struct nodo));
/* provo a leggere dal file il codice*/
/* nb=fscanf(a, "%[^&]\n",letto->isbn);*/
t=fgets(letto->isbn,LISBN,a);
/* se e' riuscito a leggere il codice t deve puntare
* a letto->isbn altrimenti e' NULL */
if(!t){
free(letto);
return NULL;
}
/* inizio a leggere il titolo con
* una lettura bufferizzata */
nb=1;
np=0;
letto->titolo=Malloc(LBUFF*sizeof(char));
getc(a); /* ignoro ``&'' */
c=(char)getc(a);
/* leggo carattere a carattere fino
* fino alla prossima '&' */
while(c!='&'){
letto->titolo[np++]=c;
if(np==LBUFF)
letto->titolo=Realloc(letto->titolo,LBUFF*sizeof(char)*++nb);
c=(char)getc(a);
}
/* termino la stringa che contiene il titolo */
letto->titolo[np]='\0';
/* leggo il codice scaffale, inizialmente lo metto in nb */
fscanf(a,"%d\n",&nb);
letto->scaffale=(unsigned char)nb;
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){
int confronto;
/* se l'albero non esiste il primo nodo e'
* sicuramente la radice */
if(!tree)return new;
/* confronto i codici per capire come
* spostarmi lungo i rami */
confronto=strcmp(tree->isbn,new->isbn);
/* se confronto e' nullo ho una chiave duplicata ! */
if(!confronto){
fprintf(stderr, "Errore chiave duplicata!\n");
exit(EXIT_FAILURE);
}
/* se confronto e' < 0 allora la chiave del nuovo nodo e' maggiore di
* quella del nodo con cui lo stiamo confrontando:
*
* se esiste il sottoalbero richiamo ricorsivamente la funzione altrimenti
* inserisco direttamente */
if(confronto<0){
if(tree->maggiori)
tree->maggiori=inserisci_in_albero(tree->maggiori, new);
else{
tree->maggiori=new;
}
}else{
if(tree->minori)
tree->minori=inserisci_in_albero(tree->minori, new);
else{
tree->minori=new;
}
}
return tree;
}
/* questa procedura ricerca nell'albero binario il libro
* tramite il codice ISBN
* e ne restituisce l'indirizzo in memoria
* se non la trova rende NULL */
struct nodo *ricerca_libro(struct nodo *a, char *c){
int confronto;
/* se il sottoalbero di ricerca non esiste ritorno
* NULL */
if(!a)return NULL;
/* utilizzo strcmp per confrontare chiave del nodo
* e chiave che sto cercando */
confronto=strcmp(a->isbn,c);
/* a seconda del risultato ho trovato la chiave o
* devo continuare la ricerca */
if(!confronto) return a;
if(confronto<0) return ricerca_libro(a->maggiori, c);
return ricerca_libro(a->minori, c);
}
/* 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;
}
/*************************************************************************/
void *Realloc(void *ptr, size_t size)
{
void *genericp;
if((genericp=realloc(ptr, size))==NULL)
{
perror("Realloc");
exit(1);
}
return genericp;
}