/******************************************************************/
/* Programma per manipolare un file contenente una lista di vini. */
/* Michele Petrocchi Matricola 256507 */
/******************************************************************/
/***********************/
/* inclusione librerie */
/***********************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*************************************/
/* Dichiarazione costanti simboliche */
/*************************************/
#define LUNGHEZZA_NOME 51 /* lunghezza della stringa del nome del vino */
#define LUNGHEZZA_CODICE 5 /* lunghezza della stringa del codice del vino */
#define LUNGHEZZA_ANNO_PRODUZIONE 5 /* lunghezza della stringa dell'anno di produzione del vino */
#define LUNGHEZZA_LUOGO_PRODUZIONE 51 /* lunghezza della stringa del luogo di produzione del vino */
#define PERCORSO_FILE "./file_vini" /* percorso del file di output */
/************************/
/* Defibizione dei tipi */
/************************/
typedef struct nodo_albero_bin
{
char nome_vino[LUNGHEZZA_NOME], /* nome del vino */
codice_vino[LUNGHEZZA_CODICE], /* codice del vino */
anno_vino[LUNGHEZZA_ANNO_PRODUZIONE], /* anno di produzione del vino */
luogo_vino[LUNGHEZZA_LUOGO_PRODUZIONE]; /* luogo di produzione del vino */
struct nodo_albero_bin *sx_p, *dx_p;
} nodo_albero_bin_t;
typedef struct vino
{
char nome_vino[LUNGHEZZA_NOME], /* nome del vino */
codice_vino[LUNGHEZZA_CODICE], /* codice del vino */
anno_vino[LUNGHEZZA_ANNO_PRODUZIONE], /* anno di produzione del vino */
luogo_vino[LUNGHEZZA_LUOGO_PRODUZIONE]; /* luogo di produzione del vino */
} vino_t;
/********************************/
/* Dichiarazione delle funzioni */
/********************************/
int controllo_correttezza_file(nodo_albero_bin_t **,
FILE *,
int *);
int inserisci_in_albero_bin(nodo_albero_bin_t ***,
char[],
char[],
char[],
char[]);
int inserisci_nuovo_vino(nodo_albero_bin_t **);
int rimuovi_vino(nodo_albero_bin_t **);
int rimuovi_da_albero_bin(nodo_albero_bin_t ***,
char[]);
void stampa_codice(nodo_albero_bin_t *);
void stampa_vini(nodo_albero_bin_t *,
int,
int);
void inserisci_vini_in_array(nodo_albero_bin_t *,
vino_t [],
int);
void quicksort_nome(vino_t [],
int,
int);
void quicksort_anno(vino_t [],
int,
int);
void quicksort_luogo(vino_t [],
int,
int);
void stampa_array(int,
vino_t *);
/******************************/
/* Definizione delle funzioni */
/******************************/
int main (int argc, /* numero stringhe acquisite lancio comandi */
char *argv[]) /* stringhe acqusite dal lancio comandi */
{
int esito = 0,
esito_ordinamento = 0,
esito_pulizia = 1,
esito_pulizia_ordinamento = 1,
scelta_utente = 0,
scelta_ordinamento = 0,
rimosso = 0,
numero_vini = 0,
controllo = 0;
FILE *input; /* file da dove preleverò la lista dei vini */
nodo_albero_bin_t *radice_p = NULL; /* lavoro: puntatore alla radice dell'albero */
/* specifichiamo il file di input, quindi deve essere 1 il numero degli argomenti */
if(argc > 1)
{
/* apriamo il file specificato */
input = fopen(argv[1],"r");
/* se il file specificato esiste */
if (input != NULL)
{
/* acquisisci il numero di vini */
esito = fscanf(input, "%d", &numero_vini);
/* se il numero di vini non è valido */
if (esito != 1 || numero_vini < 0)
printf("Lettura del numero di vini non riuscita.\n\n");
else
controllo = controllo_correttezza_file(&radice_p,
input,
&numero_vini);
/* chiudere il file di input */
fclose(input);
/* se non si sono verificati errori */
if (controllo != 1)
{
do
{
do
{
printf("\nL'utente digiti:");
printf("\n 1-Se si vuole procedere nell'inserimento di un nuovo vino");
printf("\n 2-Se si vuole procedere nella cancellazione di un altro");
printf("\n 3-Se si vuole visualizzare la lista con i vini inseriti");
printf("\n 4-Se si vuole uscire dal programma");
printf("\nPremere Invio per confermare.\n");
printf("\n");
/* pulizia del buffer della scanf */
esito_pulizia = scanf("\n");
esito = scanf("%d",
&scelta_utente);
while (getchar() != '\n');
}
while ((scelta_utente < 1) || (scelta_utente > 4) || (esito != 1) || (esito_pulizia != 0));
switch (scelta_utente)
{
case 1:
esito = inserisci_nuovo_vino(&radice_p);
if (esito == 1)
/* incrementa il numero di vini */
numero_vini++;
printf(" (premere Invio per tornare al menù)\n");
while (getchar() != '\n');
break;
case 2:
rimosso = rimuovi_vino(&radice_p);
/* se la rimozione è andata a buon fine */
if (rimosso == 1)
/* decremento il numero di vini */
numero_vini--;
printf(" (premere Invio per tornare al menù)\n");
while (getchar() != '\n');
break;
case 3:
do
{
printf("\nL'utente scelga l'ordine di visualizzaione dei vini:");
printf("\n 1-Nome");
printf("\n 2-Codice");
printf("\n 3-Luogo di produzione");
printf("\n 4-Anno di produzione");
printf("\nPremere Invio per confermare.\n");
printf("\n");
/* pulizia del buffer della scanf */
esito_pulizia_ordinamento = scanf("\n");
esito_ordinamento = scanf("%d",
&scelta_ordinamento);
while (getchar() != '\n');
}
while ((scelta_utente < 1) || (scelta_utente > 4) ||
(esito_ordinamento != 1) || (esito_pulizia_ordinamento != 0));
/* visualizzare la lista dei vini inseriti */
printf("\n%d vini inseriti:\n",
numero_vini);
if (scelta_ordinamento == 2)
/* stampa i vini in base al codice */
stampa_codice(radice_p);
else
stampa_vini(radice_p,
numero_vini,
scelta_ordinamento);
printf("\n");
printf("(premere Invio per tornare al menù)\n");
while (getchar() != '\n');
break;
case 4:
/* se l'utente decide di uscire stampiamo un messaggio di saluto */
printf("\nGrazie per aver utilizzato questo programma!");
printf("\n\n");
break;
}
}
while ((scelta_utente != 4));
}
}
else/* se il file specificato è uguale a NULL e quindi inesistente */
printf("\nIl file specificato non esiste!\n");
}
else
{
/* se non è stato inserito il parametro di lancio del file */
printf("\nNon è stato immesso il nome del file da dove importare i dati riguardanti i vini!");
printf("\nrilanciare il programma con queste specifiche:");
printf("\n./<nome_eseguibile> <nome_file_input>\n");
printf("\nIl file può essere generato tramite il programma che viene lanciato con ./genera");
printf("\n(per la compilazione il comando è make genera_vini!)\n");
printf("\n(se il file è nella dir. di lavoro basta specificarne il nome!)\n\n");
}
return(0);
}
int controllo_correttezza_file(nodo_albero_bin_t **radice_p,
FILE * input,
int *numero_vini)
{
int esito,
controllo_errori = 0,
i, j;
char nome_vino[LUNGHEZZA_NOME],
codice_vino[LUNGHEZZA_CODICE],
anno_vino[LUNGHEZZA_ANNO_PRODUZIONE],
luogo_vino[LUNGHEZZA_LUOGO_PRODUZIONE],
carattere_acquisito = '~'; /* lavoro: variabile utilizzata */
/* per acquisizioni e controlli */
/* il ciclo acquisce i vini uno ad uno dal file e li inserisce nella struttura dati */
for (i = 0; ((i < *numero_vini) && (controllo_errori == 0)); i++)
{
/* scorro il file fino a trovare il carattere successivo */
while (carattere_acquisito != '\n')
carattere_acquisito = getc(input);
/* acquisizione del nome del vino */
for (j = 0, carattere_acquisito = '~';
((j < (LUNGHEZZA_NOME - 1)) && (carattere_acquisito != ' ')
&& (carattere_acquisito != '\n') && (controllo_errori == 0));
j++)
{
carattere_acquisito = getc(input);
if ((carattere_acquisito != ' ') && (carattere_acquisito != '\n'))
nome_vino[j] = carattere_acquisito;
else
j--;
}
nome_vino[j] = '\0';
/* se il nome del vino ha più caratteri del previsto */
if (carattere_acquisito != ' ')
printf("I nomi che superano i %d caratteri sono stati abbreviati!\n",
(LUNGHEZZA_NOME - 1));
/* spostati in avanti nel file in avanti fino ad arrivare all'inizio del codice */
while (carattere_acquisito != ' ')
carattere_acquisito = getc(input);
/* acquisizione del codice del vino */
for (j = 0;
((j < (LUNGHEZZA_CODICE - 1)) && (controllo_errori == 0));
j++)
{
codice_vino[j] = getc(input);
/* se il codice vino ha meno caratteri del previsto */
if (codice_vino[j] == ' ')
{
printf("I codici dei vini devono contenere %d caratteri!\n",
(LUNGHEZZA_CODICE - 1));
controllo_errori = 1;
}
/* se il codice contiene caratteri non alfanumerici */
else if (codice_vino[j] < '0' || (codice_vino[j] > '9' && codice_vino[j] < 'A') ||
(codice_vino[j] > 'Z' && codice_vino[j] < 'a') || codice_vino[j] > 'z')
{
printf("I codici dei vini possono contenere solo caratteri alfanumerici!\n");
/* forza la chiusura del programma */
controllo_errori = 1;
}
}
codice_vino[j] = '\0';
carattere_acquisito = getc(input);
/* spostati in avanti nel file fino ad arrivare all'inizio dell'anno di produzione */
while (carattere_acquisito != ' ')
carattere_acquisito = getc(input);
/* acquisizione dell'anno di produzione */
for (j = 0, carattere_acquisito = '~';
((j < (LUNGHEZZA_ANNO_PRODUZIONE - 1)) && (controllo_errori == 0));
j++)
{
anno_vino[j] = getc(input);
/* se l'anno del vino ha meno caratteri del previsto */
if (anno_vino[j] == ' ')
{
printf("L'anno di produzione dei vini devono contenere %d caratteri!\n",
(LUNGHEZZA_ANNO_PRODUZIONE - 1));
controllo_errori = 1;
}
/* se l'anno contiene caratteri non numerici */
else if (anno_vino[j] < '0' || anno_vino[j] > '9' )
{
printf("Gli anni dei vini possono contenere solo caratteri numerici!\n");
/* forza la chiusura del programma */
controllo_errori = 1;
}
}
anno_vino[j] = '\0';
carattere_acquisito = getc(input);
/* spostati in avanti nel file in avanti fino ad arrivare all'inizio del luogo di produzione */
while (carattere_acquisito != ' ')
carattere_acquisito = getc(input);
/* acquisizione del luogo di produzione del vino */
for (j = 0, carattere_acquisito = '~';
((j < (LUNGHEZZA_LUOGO_PRODUZIONE - 1)) && (carattere_acquisito != ' ')
&& (carattere_acquisito != '\n') && (controllo_errori == 0));
j++)
{
carattere_acquisito = getc(input);
if ((carattere_acquisito != ' ') && (carattere_acquisito != '\n'))
luogo_vino[j] = carattere_acquisito;
else
j--;
}
luogo_vino[j] = '\0';
/* se il luogo di produzione del vino ha più caratteri del previsto */
if ((carattere_acquisito != '\n') && (controllo_errori == 0))
printf("I luoghi che superano i %d caratteri sono stati abbreviati!\n",
(LUNGHEZZA_LUOGO_PRODUZIONE - 1));
/* inserimento del vino nell'albero ordinato secondo il codice */
esito = inserisci_in_albero_bin(&radice_p,
codice_vino,
nome_vino,
anno_vino,
luogo_vino);
/* se l'inserimento non è andato a buon fine */
if (esito == 0)
{
printf("\nIl vino con codice \"%s\" non è stato inserito perchè già presente nella lista!\n",
codice_vino);
/* decrementa il numero dei vini del numero di inserimenti falliti */
*numero_vini = *numero_vini - 1;
}
}
return (controllo_errori);
}
/* Algoritmo per l'inserimento di un vino nell'albero binario ordinato secondo il codice */
int inserisci_in_albero_bin(nodo_albero_bin_t ***radice_p, /* lavoro: puntatore al puntatore alla radice dell'albero */
char codice_vino[], /* input: codice del vino da inserire */
char nome_vino[], /* input: nome del vino da inserire */
char anno_vino[], /* input: anno di produzione del vino da inserire */
char luogo_vino[]) /* input: luogo di produzione del vino da inserire */
{
int inserito, /* output: esito dell'inserimento */
i; /* lavoro: indice per i cicli for */
nodo_albero_bin_t *nodo_p, /* lavoro: puntatore ad un nodo */
*padre_p, /* lavoro: puntatore al padre del nodo_p */
*nuovo_p; /* lavoro: puntatore al nodo che conterrà il nuovo vino */
/* nodo_p e padre_p vengono inizializzati con l'indirizzo della radice e ad ogni */
/* iterazione padre_p prende l'indirizzo di nodo_p.nodo_p prende l'indirizzo del */
/* suo figlio sx o dx a seconda che il codice da inserire sia < o >= al codice */
/* puntato da nodo_p.Il ciclo termina quando nodo_p punta a NULL oppure ad un */
/* elemento che contiene un codice uguale a quello da inserire. */
for (nodo_p = padre_p = **radice_p;
((nodo_p != NULL) && (strcmp(nodo_p->codice_vino, codice_vino) != 0));
padre_p = nodo_p, nodo_p = (strcmp(codice_vino, nodo_p->codice_vino) < 0)?
nodo_p->sx_p:
nodo_p->dx_p);
/* il vino non verrà inserito se era già presente, ovvero se nodo_p non punta a NULL */
if (nodo_p != NULL)
inserito = 0;
else
{
inserito = 1;
/* viene allocata memoria per il nuovo nodo */
nuovo_p = (nodo_albero_bin_t *)malloc(sizeof(nodo_albero_bin_t));
/* inserimento del codice del vino */
for (i = 0; (i < LUNGHEZZA_CODICE); i++)
nuovo_p->codice_vino[i] = codice_vino[i];
/* inserimento del nome del vino */
for (i = 0; (i < LUNGHEZZA_NOME); i++)
nuovo_p->nome_vino[i] = nome_vino[i];
/* inserimento dell'anno di produzione del vino */
for (i = 0; (i < LUNGHEZZA_ANNO_PRODUZIONE); i++)
nuovo_p->anno_vino[i] = anno_vino[i];
/* inserimento del luogo di produzione del vino */
for (i = 0; (i < LUNGHEZZA_LUOGO_PRODUZIONE); i++)
nuovo_p->luogo_vino[i] = luogo_vino[i];
/* i puntatori vengono inizializzati a NULL */
nuovo_p->sx_p = nuovo_p->dx_p = NULL;
/* se il nodo si trova in cima all'albero diventa la radice */
if (nodo_p == **radice_p)
**radice_p = nuovo_p;
/* se il codice inserito è inferiore a quello contenuto nel nodo padre */
else if (strcmp(codice_vino, padre_p->codice_vino) < 0)
/* il nuovo nodo diventa figlio sinistro */
padre_p->sx_p = nuovo_p;
else
/* il nuovo nodo diventa figlio destro */
padre_p->dx_p = nuovo_p;
}
/* viene restituito il valore di esito dell'inserimento */
return(inserito);
}
/* Funzione per l'inserimento di un nuovo vino */
int inserisci_nuovo_vino(nodo_albero_bin_t **radice_p) /* lavoro: puntatore alla radice dell'albero */
{
char nome_vino[LUNGHEZZA_NOME], /* input: nome del vino da inserire */
codice_vino[LUNGHEZZA_CODICE], /* input: codice del vino da inserire */
anno_vino[LUNGHEZZA_ANNO_PRODUZIONE], /* input: anno di produzione del vino da inserire */
luogo_vino[LUNGHEZZA_LUOGO_PRODUZIONE], /* input: luogo di produzione del vino da inserire */
carattere_acquisito = '~'; /* lavoro: variabile usata per acquisizioni e controlli */
int inserito = 0, /* output: esito dell'inserimento */
controllo_errori, /* lavoro: variabile di controllo */
i; /* lavoro: indice per i cicli for */
/* acquisizione del codice del vino da inserire */
printf("\nScrivere il codice del vino da inserire: ");
/* non esce dal ciclo se il codice inserito da tastiera è troppo corto */
do
{
controllo_errori = 0;
carattere_acquisito = '~';
for (i = 0;
((i < (LUNGHEZZA_CODICE - 1)) && (carattere_acquisito != '\n')
&& (carattere_acquisito != ' ') && (controllo_errori == 0));
i++)
{
carattere_acquisito = getchar();
if ((carattere_acquisito != '\n') && (carattere_acquisito != ' '))
codice_vino[i] = carattere_acquisito;
else
{
i--;
printf("\nIl codice deve contenere %d caratteri alfanumerici!\n",
(LUNGHEZZA_CODICE - 1));
printf("\nRiscrivere il codice del vino: ");
}
/* se il codice contiene caratteri non alfanumerici */
if (codice_vino[i] < '0' || (codice_vino[i] > '9' && codice_vino[i] < 'A') ||
(codice_vino[i] > 'Z' && codice_vino[i] < 'a') || codice_vino[i] > 'z')
{
controllo_errori = 1;
printf("\nRiscrivere il codice del vino: ");
}
}
codice_vino[i] = '\0';
}
while ((strlen(codice_vino) != (LUNGHEZZA_CODICE - 1)) || (controllo_errori == 1));
carattere_acquisito = getchar();
/* se l'utente ha inserito un codice troppo lungo */
if (carattere_acquisito != '\n')
/* ripulisci il file stdin */
while (carattere_acquisito != '\n')
carattere_acquisito = getchar();
/* acquisizione del nome del vino da inserire */
/* non esce dal ciclo se l'utente non inserisce nessun nome */
do
{
printf("Scrivere il nome del vino da inserire: ");
carattere_acquisito = '~';
for (i = 0;
((i < (LUNGHEZZA_NOME - 1)) && (carattere_acquisito != '\n') && (carattere_acquisito != ' '));
i++)
{
carattere_acquisito = getchar();
if ((carattere_acquisito != '\n') && (carattere_acquisito != ' '))
nome_vino[i] = carattere_acquisito;
else
i--;
}
nome_vino[i] = '\0';
/* se l'utente ha inserito un nome troppo lungo */
if ((carattere_acquisito != '\n') && (carattere_acquisito != ' '))
{
printf("\nIl nome è stato abbreviato a %d caratteri!\n\n",
(LUNGHEZZA_NOME - 1));
/* ripulisci il file stdin */
while (carattere_acquisito != '\n')
carattere_acquisito = getchar();
}
}
while (strlen(nome_vino) == 0);
/* acquisizione dell'anno di produzione del vino da inserire */
printf("Scrivere l'anno di produzione del vino da inserire: ");
/* non esce dal ciclo se l'anno inserito da tastiera è troppo corto */
do
{
controllo_errori = 0;
carattere_acquisito = '~';
for (i = 0;
((i < (LUNGHEZZA_ANNO_PRODUZIONE - 1)) && (carattere_acquisito != '\n')
&& (carattere_acquisito != ' ') && (controllo_errori == 0));
i++)
{
carattere_acquisito = getchar();
if ((carattere_acquisito != '\n') && (carattere_acquisito != ' '))
anno_vino[i] = carattere_acquisito;
else
{
i--;
printf("\nL'anno deve contenere %d caratteri numerici!\n",
(LUNGHEZZA_ANNO_PRODUZIONE - 1));
printf("\nRiscrivere l'anno di produzione del vino: ");
}
/* se l'anno contiene caratteri non numerici */
if (anno_vino[i] < '0' || anno_vino[i] > '9')
controllo_errori = 1;
}
anno_vino[i] = '\0';
}
while ((strlen(anno_vino) != (LUNGHEZZA_ANNO_PRODUZIONE - 1)) || (controllo_errori == 1));
carattere_acquisito = getchar();
/* se l'utente ha inserito un anno troppo lungo */
if (carattere_acquisito != '\n')
/* ripulisci il file stdin */
while (carattere_acquisito != '\n')
carattere_acquisito = getchar();
/* acquisizione del luogo di produzione del vino da inserire */
/* non esce dal ciclo se l'utente non inserisce nessun luogo */
do
{
printf("Scrivere il luogo di produzione del vino da inserire: ");
carattere_acquisito = '~';
for (i = 0;
((i < (LUNGHEZZA_LUOGO_PRODUZIONE - 1)) && (carattere_acquisito != '\n') && (carattere_acquisito != ' '));
i++)
{
carattere_acquisito = getchar();
if ((carattere_acquisito != '\n') && (carattere_acquisito != ' '))
luogo_vino[i] = carattere_acquisito;
else
i--;
}
luogo_vino[i] = '\0';
/* se l'utente ha inserito un luogo troppo lungo */
if (carattere_acquisito != '\n')
{
printf("\nIl luogo è stato abbreviato a %d caratteri!\n\n",
(LUNGHEZZA_LUOGO_PRODUZIONE - 1));
/* ripulisci il file stdin */
while (carattere_acquisito != '\n')
carattere_acquisito = getchar();
}
}
while (strlen(luogo_vino) == 0);
/* inserimento del vino nell'albero */
inserito = inserisci_in_albero_bin(&radice_p,
codice_vino,
nome_vino,
anno_vino,
luogo_vino);
/* se l'inserimento è andato a buon fine */
if (inserito != 1)
printf("\nVino \"%s\" già presente!", codice_vino);
else
printf("\nIl vino è stato inserito.");
/* viene restituito l'esito dell'inserimento */
return (inserito);
}
int rimuovi_vino(nodo_albero_bin_t **radice_p) /* lavoro: puntatore alla radice dell'albero */
{
char codice_vino[LUNGHEZZA_CODICE], /* input: codice del vino da rimuovere */
carattere_acquisito = '~'; /* lavoro: variabile usata per acquisizioni e controlli */
int rimosso = 0, /* output: esito rimozione */
controllo_errori, /* lavoro: variabile di controllo */
i; /* lavoro: indice per i cicli */
/* acquisizione del codice del vino da rimuovere */
printf("\nScrivere il codice del vino da rimuovere: ");
/* non esce dal ciclo se l'utente non inserisce un codice corretto */
do
{
controllo_errori = 0;
carattere_acquisito = '~';
for (i = 0;
((i < (LUNGHEZZA_CODICE - 1)) && (carattere_acquisito != '\n')
&& (carattere_acquisito != ' ') && (controllo_errori == 0));
i++)
{
carattere_acquisito = getchar();
if ((carattere_acquisito != '\n') && (carattere_acquisito != ' '))
codice_vino[i] = carattere_acquisito;
else
{
i--;
printf("\nIl codice deve contenere %d caratteri alfanumerici!\n",
(LUNGHEZZA_CODICE - 1));
printf("\nRiscrivere il codice del vino: ");
}
/* se il codice contiene caratteri non alfanumerici */
if (codice_vino[i] < '0' || (codice_vino[i] > '9' && codice_vino[i] < 'A') ||
(codice_vino[i] > 'Z' && codice_vino[i] < 'a') || codice_vino[i] > 'z')
{
controllo_errori = 1;
printf("\nRiscrivere il codice del vino: ");
}
}
codice_vino[i] = '\0';
}
while ((strlen(codice_vino) != (LUNGHEZZA_CODICE - 1)) || (controllo_errori == 1));
carattere_acquisito = getchar();
/* se l'utente ha inserito un codice troppo lungo */
if (carattere_acquisito != '\n')
/* ripulisci il file stdin */
while (carattere_acquisito != '\n')
carattere_acquisito = getchar();
/* rimozione del vino dall'albero */
rimosso = rimuovi_da_albero_bin(&radice_p,
codice_vino);
if (rimosso == 1)
printf("\nIl vino è stato rimosso!");
else
printf("\nIl vino non è presente nella lista!");
/* viene restituito l'esito della rimozione */
return (rimosso);
}
/* Algoritmo per la rimozione di un vino dall'albero binario */
int rimuovi_da_albero_bin(nodo_albero_bin_t ***radice_p, /* lavoro: puntatore al puntatore alla radice dell'albero */
char codice_vino[]) /* input: codice del vino da rimuovere */
{
int rimosso, /* output: esito della rimozione */
i; /* lavoro: contatore per i cicli for */
nodo_albero_bin_t *nodo_p, /* lavoro: puntatore a un nodo */
*padre_p, /* lavoro: padre di nodo_p */
*sost_p; /* lavoro: sostituto di nodo_p */
/* nodo_p e padre_p vengono inizializzati con l'indirizzo della radice e ad ogni */
/* iterazione padre_p prende l'indirizzo di nodo_p.nodo_p prende l'indirizzo del */
/* suo figlio sx o dx a seconda che il codice da inserire sia < o >= al codice */
/* puntato da nodo_p.Il ciclo termina quando nodo_p punta a NULL oppure ad un */
/* elemento che contiene un codice uguale a quello da rimuovere. */
for (nodo_p = padre_p = **radice_p;
((nodo_p != NULL) && (strcmp(nodo_p->codice_vino,codice_vino) != 0));
padre_p = nodo_p, nodo_p = (strcmp(codice_vino,nodo_p->codice_vino) < 0)?
nodo_p->sx_p:
nodo_p->dx_p);
/* il vino non verrà rimosso se non era presente, ovvero se nodo_p punta a NULL */
if (nodo_p == NULL)
rimosso = 0;
else
{
rimosso = 1;
/* se nodo_p non ha figlio sx */
if (nodo_p->sx_p == NULL)
{
/* se nodo_p si trova in cima all'albero */
if (nodo_p == **radice_p)
/* il figlio destro del nodo diventa la radice */
**radice_p = nodo_p->dx_p;
/* altrimenti se il codice da rimuovere è minore di quello del padre */
else if (strcmp(codice_vino, padre_p->codice_vino) < 0)
/* il figlio destro del nodo_p, diventa figlio sinistro del padre */
padre_p->sx_p = nodo_p->dx_p;
else
/* il figlio destro del nodo_p, diventa figlio destro del padre */
padre_p->dx_p = nodo_p->dx_p;
}
/* altrimenti, se nodo_p non ha figlio destro */
else if (nodo_p->dx_p == NULL)
{
/* se nodo_p si trova in cima all'albero */
if (nodo_p == **radice_p)
/* il figlio sinistro del nodo diventa la radice */
**radice_p = nodo_p->sx_p;
/* altrimenti, se il codice da rimuovere è minore di quello del padre */
else if (strcmp(codice_vino, padre_p->codice_vino) < 0)
/* il figlio sinistro del nodo_p diventa figlio sinistro del padre */
padre_p->sx_p = nodo_p->sx_p;
else
/* il figlio sinistro del nodo_p diventa figlio destro del padre */
padre_p->dx_p = nodo_p->sx_p;
}
/* altrimenti, se il nodo_p ha entrambi i figli */
else
{
/* sost_p prende l'indirizzo contenuto in nodo_p */
sost_p = nodo_p;
/* ad ogni iterazione del ciclo, padre_p prende l'indirizzo di nodo_p e nodo_p prende */
/* l'indirizzo del figlio destro; il ciclo termina quando nodo_p non ha figlio destro */
for (padre_p = sost_p, nodo_p = sost_p->sx_p;
(nodo_p->dx_p != NULL);
padre_p = nodo_p, nodo_p = nodo_p->dx_p);
/* sostuzione del codice del nodo sost_p con quello del nodo_p */
for (i = 0; (i < LUNGHEZZA_CODICE); i++)
sost_p->codice_vino[i] = nodo_p->codice_vino[i];
/* sostituzione del nome del nodo sost_p con quello del nodo_p */
for (i = 0; (i < LUNGHEZZA_NOME); i++)
sost_p->nome_vino[i] = nodo_p->nome_vino[i];
/* sostuzione dell'anno del nodo sost_p con quello del nodo_p */
for (i = 0; (i < LUNGHEZZA_ANNO_PRODUZIONE); i++)
sost_p->anno_vino[i] = nodo_p->anno_vino[i];
/* sostituzione del luogo del nodo sost_p con quello del nodo_p */
for (i = 0; (i < LUNGHEZZA_LUOGO_PRODUZIONE); i++)
sost_p->anno_vino[i] = nodo_p->anno_vino[i];
/* se padre_p e sost_p puntano allo stesso nodo */
if (padre_p == sost_p)
/* il figlio sinistro del nodo_p diventa figlio sinistro del padre_p */
padre_p->sx_p = nodo_p->sx_p;
else
/* il figlio sinistro del nodo_p diventa figlio destro del padre_p */
padre_p->dx_p = nodo_p->sx_p;
}
/* il nodo puntato da nodo_p viene rimosso dalla memoria */
free(nodo_p);
}
return(rimosso);
}
/* funzione per la stampa dei vini in base al codice */
void stampa_codice(nodo_albero_bin_t *nodo_p)
{
if (nodo_p != NULL)
{
stampa_codice(nodo_p->sx_p);
printf("%s %s %s %s\n",
nodo_p->nome_vino,
nodo_p->codice_vino,
nodo_p->anno_vino,
nodo_p->luogo_vino);
stampa_codice(nodo_p->dx_p);
}
}
void stampa_vini(nodo_albero_bin_t *radice_p,
int numero_vini,
int scelta_ordinamento)
{
vino_t vini[numero_vini]; /* array per l'ordinamento */
/* trasferimento dei vini dall'albero in un array */
inserisci_vini_in_array(radice_p,
vini,
0);
switch(scelta_ordinamento)
{
case 1:
/* ordina i vini in base al nome */
quicksort_nome(vini,
0,
numero_vini - 1);
break;
case 3:
/* ordina i vini in base all'anno */
quicksort_anno(vini,
0,
numero_vini - 1);
break;
case 4:
/* ordina i vini in base al luogo */
quicksort_luogo(vini,
0,
numero_vini - 1);
break;
}
stampa_array(numero_vini,
vini);
}
/* funzione per il trasferimento dei vini dall'albero in un array */
void inserisci_vini_in_array(nodo_albero_bin_t *nodo_p,
vino_t *vini,
int i)
{
if (nodo_p->codice_vino != NULL)
{
inserisci_vini_in_array(nodo_p->sx_p,
vini,
i);
strcpy(vini[i].nome_vino, nodo_p->nome_vino);
strcpy(vini[i].codice_vino, nodo_p->codice_vino);
strcpy(vini[i].anno_vino, nodo_p->anno_vino);
strcpy(vini[i].luogo_vino, nodo_p->luogo_vino);
i = i + 1;
inserisci_vini_in_array(nodo_p->dx_p,
vini,
i);
}
}
void quicksort_nome(vino_t a[],
int sx,
int dx)
{
int i, j; /* variabili di lavoro */
vino_t tmp, /* variabile usata per lo scambio */
pivot; /* puntatore all'elemento che fungera' da pivot */
/* si sceglie come pivot il valore centrale e si attua una tri-partizione */
/* scambiando gli elementi in modo che nella porzione a destra del pivot vi */
/* siano elementi maggiori del pivot e nella porzione sinistra quelli minori */
for (pivot = a[(sx + dx) / 2], i = sx, j = dx; (i <= j);)
{
while (strcmp(a[i].nome_vino, pivot.nome_vino) == -1)
i++;
while (strcmp(a[j].nome_vino, pivot.nome_vino) == 1)
j--;
if (i <= j)
{
if (i < j)
{
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
i++;
j--;
}
}
/* si invoca ricorsivamente la funzione sulle porzioni sinistra e destra */
if (sx < j)
quicksort_nome(a, sx, j);
if (i < dx)
quicksort_nome(a, i, dx);
}
void quicksort_anno(vino_t a[],
int sx,
int dx)
{
int i, j; /* variabili di lavoro */
vino_t tmp, /* variabile usata per lo scambio */
pivot; /* puntatore all'elemento che fungera' da pivot */
/* si sceglie come pivot il valore centrale e si attua una tri-partizione */
/* scambiando gli elementi in modo che nella porzione a destra del pivot vi */
/* siano elementi maggiori del pivot e nella porzione sinistra quelli minori */
for (pivot = a[(sx + dx) / 2], i = sx, j = dx; (i <= j);)
{
while (strcmp(a[i].anno_vino, pivot.anno_vino) == -1)
i++;
while (strcmp(a[j].anno_vino, pivot.anno_vino) == 1)
j--;
if (i <= j)
{
if (i < j)
{
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
i++;
j--;
}
}
/* si invoca ricorsivamente la funzione sulle porzioni sinistra e destra */
if (sx < j)
quicksort_anno(a, sx, j);
if (i < dx)
quicksort_anno(a, i, dx);
}
void quicksort_luogo(vino_t a[],
int sx,
int dx)
{
int i, j; /* variabili di lavoro */
vino_t tmp, /* variabile usata per lo scambio */
pivot; /* puntatore all'elemento che fungera' da pivot */
/* si sceglie come pivot il valore centrale e si attua una tri-partizione */
/* scambiando gli elementi in modo che nella porzione a destra del pivot vi */
/* siano elementi maggiori del pivot e nella porzione sinistra quelli minori */
for (pivot = a[(sx + dx) / 2], i = sx, j = dx; (i <= j);)
{
while (strcmp(a[i].luogo_vino, pivot.luogo_vino) == -1)
i++;
while (strcmp(a[j].luogo_vino, pivot.luogo_vino) == 1)
j--;
if (i <= j)
{
if (i < j)
{
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
i++;
j--;
}
}
/*Si invoca ricorsivamente la funzione sulle porzioni sinistra e destra*/
if (sx < j)
quicksort_luogo(a, sx, j);
if (i < dx)
quicksort_luogo(a, i, dx);
}
void stampa_array(int numero_vini,
vino_t *vini)
{
int i;
/*Vengono stampati gli elementi ordinati*/
for(i = 0; i < numero_vini; i++)
printf("\n%20s %4s %4s %s",
vini[i].nome_vino,
vini[i].codice_vino,
vini[i].anno_vino,
vini[i].luogo_vino);
}