/* possibile soluzione all'esame del 26.6.2000*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
/* per alcuni campi il testo non fissa una lunghezza, ma neanche
* dice di non farlo, ne fisso io una ragionevole */
#define ML 255
/* nodo dell'albero binario di ricerca */
struct nodo{
char descrizione[255];
unsigned long prezzo; /* su 16 bit e' opportuno il long */
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 inorder(struct nodo *);
int ricerca(struct nodo*, char *);
void libera_albero(struct nodo *a);
/* 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_beni=NULL;
/* dati negozio (il testo non precisa niente
* sulla lunghezza massima, ne fisso io una ragionevole */
char denominazione[ML];
char p_iva[ML];
char indirizzo[ML];
int ii,jj;
/* file handler per lettura */
FILE *dati;
/* comando inserito */
char code;
/* prodotto da ricercare */
char prodotto[ML];
/* carrello (e' solo il prezzo finale) */
unsigned long carrello=0;
/* PRIMA PARTE: leggo e interpreto il file */
dati=Fopen("CASSA.DAT","r");
/* innanzitutto leggo le prime tre righe
* la sintassi di fscanf, mi permette la lettura di tre righe complete */
ii=fscanf(dati, "%[^\n]\n%[^\n]\n%[^\n]\n", denominazione, p_iva, indirizzo);
if(ii!=3){
fprintf(stderr, "Errore in file !\n");
exit(EXIT_FAILURE);
}
while(1){
tmp=leggi_riga(dati);
if(!tmp)break;
/* inserisco i dati nell'albero binario */
albero_beni=inserisci_in_albero(albero_beni, tmp);
}
/* SECONDA PARTE: iterativamente chiedo un tasto
* ed eseguo l'operazione relativa */
while(1){
printf("Inserisci un comando: ");
code=(char)toupper(getchar());
/* leggo un tasto e lo converto in maiuscolo
* purtroppo l'ANSI C non contiene funzioni
* ``pratiche'' per la
* lettura di un singolo tasto */
getchar(); /* mi elimina il \n nel buffer */
switch(code){
case 'L':
printf("\nElenco beni e relativo prezzo:\n\n");
inorder(albero_beni);
break;
case 'A':
printf("Inserisci prodotto: ");
fgets(prodotto, 255, stdin);
/* fgets incamera anche l'\n' che va elminato */
prodotto[strlen(prodotto)-1]='\0';
printf("Sto ricercando: %s\n",prodotto);
ii=ricerca(albero_beni, prodotto);
if(!ii){
printf("Attenzione: prodotto non trovato\n");
printf("Carrello: %ld\n", carrello);
}
else{
printf("Prezzo : %d\n", ii);
printf("Inserisci quantità: ");
scanf("%d",&jj);
getchar(); /* elimino il \n */
carrello+=ii*jj;
printf("Carrello: %ld\n", carrello);
}
break;
case 'S':
printf("\n%s\n", denominazione);
printf("%s\n", p_iva);
printf("%s\n", indirizzo);
printf("TOTALE: %ld\n\n", carrello);
carrello=0;
break;
case 'U':
libera_albero(albero_beni);
exit(EXIT_SUCCESS);
default:
break;
}
}
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));
/* provo a leggere dal file la descrizione */
nb=fscanf(a, "%[^#]#",letto->descrizione);
/* se e' riuscito a leggere la descrizione nb deve essere
* pari ad uno */
if(nb!=1){
free(letto);
return NULL;
}
/* leggo il prezzo del bene */
fscanf(a,"%ld\n",&letto->prezzo);
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->descrizione,new->descrizione);
/* 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 bene
* tramite la descrizione,
* ne restituisce il prezzo oppure 0 */
int ricerca(struct nodo *a, char *c){
int confronto;
/* se il sottoalbero di ricerca non esiste ritorno
* 0 */
if(!a)return 0;
/* utilizzo strcmp per confrontare chiave del nodo
* e chiave che sto cercando */
confronto=strcmp(a->descrizione,c);
/* a seconda del risultato ho trovato la chiave o
* devo continuare la ricerca */
if(!confronto) return a->prezzo;
if(confronto<0) return ricerca(a->maggiori, c);
return ricerca(a->minori, c);
}
/* E' un semplice attraversamento (il fatto che sia inorder non
* e' significativo), mi permette di stampare la lista beni e
* relativi prezzi */
void inorder(struct nodo *a){
if(!a)return;
inorder(a->maggiori);
printf("%s - %ld\n", a->descrizione, a->prezzo);
inorder(a->minori);
}
/* libero le strutture allocate dinamicamente prima di uscire */
void libera_albero(struct nodo *a){
if(!a)return;
libera_albero(a->maggiori);
libera_albero(a->minori);
free(a);
}
/* 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;
}