Oppure

Loading
27/01/14 17:35
mik_91
Nel file allegato vi è il codice di un programma che gestisce un database di vini. Il mio problema è che ricevo un errore di segmentazione entrando nella funzione "inserisci_in_albero_bin". E' da un pò di giorni che stò cercando una soluzione ma non riesco a venirne a capo...qualcuno saprebbe aiutarmi??
/******************************************************************/
/* 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] = 'Nel file allegato vi è il codice di un programma che gestisce un database di vini. Il mio problema è che ricevo un errore di segmentazione entrando nella funzione "inserisci_in_albero_bin". E' da un pò di giorni che stò cercando una soluzione ma non riesco a venirne a capo...qualcuno saprebbe aiutarmi??

/******************************************************************/
/* 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] = '{parsed_message}';

		/* 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] = '{parsed_message}';

		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] = '{parsed_message}';

		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] = '{parsed_message}';
  
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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);
}
'; /* 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] = 'Nel file allegato vi è il codice di un programma che gestisce un database di vini. Il mio problema è che ricevo un errore di segmentazione entrando nella funzione "inserisci_in_albero_bin". E' da un pò di giorni che stò cercando una soluzione ma non riesco a venirne a capo...qualcuno saprebbe aiutarmi??
/******************************************************************/
/* 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] = '{parsed_message}';

		/* 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] = '{parsed_message}';

		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] = '{parsed_message}';

		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] = '{parsed_message}';
  
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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);
}
'; 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] = 'Nel file allegato vi è il codice di un programma che gestisce un database di vini. Il mio problema è che ricevo un errore di segmentazione entrando nella funzione "inserisci_in_albero_bin". E' da un pò di giorni che stò cercando una soluzione ma non riesco a venirne a capo...qualcuno saprebbe aiutarmi??
/******************************************************************/
/* 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] = '{parsed_message}';

		/* 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] = '{parsed_message}';

		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] = '{parsed_message}';

		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] = '{parsed_message}';
  
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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);
}
'; 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] = 'Nel file allegato vi è il codice di un programma che gestisce un database di vini. Il mio problema è che ricevo un errore di segmentazione entrando nella funzione "inserisci_in_albero_bin". E' da un pò di giorni che stò cercando una soluzione ma non riesco a venirne a capo...qualcuno saprebbe aiutarmi??
/******************************************************************/
/* 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] = '{parsed_message}';

		/* 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] = '{parsed_message}';

		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] = '{parsed_message}';

		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] = '{parsed_message}';
  
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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);
}
'; /* 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] = 'Nel file allegato vi è il codice di un programma che gestisce un database di vini. Il mio problema è che ricevo un errore di segmentazione entrando nella funzione "inserisci_in_albero_bin". E' da un pò di giorni che stò cercando una soluzione ma non riesco a venirne a capo...qualcuno saprebbe aiutarmi??
/******************************************************************/
/* 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] = '{parsed_message}';

		/* 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] = '{parsed_message}';

		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] = '{parsed_message}';

		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] = '{parsed_message}';
  
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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);
}
'; } 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] = 'Nel file allegato vi è il codice di un programma che gestisce un database di vini. Il mio problema è che ricevo un errore di segmentazione entrando nella funzione "inserisci_in_albero_bin". E' da un pò di giorni che stò cercando una soluzione ma non riesco a venirne a capo...qualcuno saprebbe aiutarmi??
/******************************************************************/
/* 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] = '{parsed_message}';

		/* 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] = '{parsed_message}';

		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] = '{parsed_message}';

		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] = '{parsed_message}';
  
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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);
}
'; /* 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] = 'Nel file allegato vi è il codice di un programma che gestisce un database di vini. Il mio problema è che ricevo un errore di segmentazione entrando nella funzione "inserisci_in_albero_bin". E' da un pò di giorni che stò cercando una soluzione ma non riesco a venirne a capo...qualcuno saprebbe aiutarmi??
/******************************************************************/
/* 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] = '{parsed_message}';

		/* 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] = '{parsed_message}';

		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] = '{parsed_message}';

		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] = '{parsed_message}';
  
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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);
}
'; } 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] = 'Nel file allegato vi è il codice di un programma che gestisce un database di vini. Il mio problema è che ricevo un errore di segmentazione entrando nella funzione "inserisci_in_albero_bin". E' da un pò di giorni che stò cercando una soluzione ma non riesco a venirne a capo...qualcuno saprebbe aiutarmi??
/******************************************************************/
/* 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] = '{parsed_message}';

		/* 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] = '{parsed_message}';

		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] = '{parsed_message}';

		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] = '{parsed_message}';
  
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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);
}
'; /* 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] = 'Nel file allegato vi è il codice di un programma che gestisce un database di vini. Il mio problema è che ricevo un errore di segmentazione entrando nella funzione "inserisci_in_albero_bin". E' da un pò di giorni che stò cercando una soluzione ma non riesco a venirne a capo...qualcuno saprebbe aiutarmi??
/******************************************************************/
/* 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] = '{parsed_message}';

		/* 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] = '{parsed_message}';

		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] = '{parsed_message}';

		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] = '{parsed_message}';
  
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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] = '{parsed_message}';
     
		/* 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] = '{parsed_message}';
	}
	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);
}
'; } 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); }
Ultima modifica effettuata da mik_91 27/01/14 17:39
aaa
27/01/14 18:08
quello che non so come si chiama
Puoi allegare un esempio di file di input?
aaa
27/01/14 18:20
nessuno
Mi sa che un tuo collega stava affrontando lo stesso esercizio in

iprogrammatori.it/forum-programmazione/cplusplus/…

e a parte un problema risolto, gli funzionava ...

Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
28/01/14 7:59
mik_91
si, è simile...lui usa una lista e io un albero, però nell'inserimento, come nella cancellazione di una nodo nell'albero non ho problemi..ne ho più tardi quando devo stampare la lista dei vini ordinata.
Di seguito riporto un esempio generico di file:

4 vini inseriti:
Nwlrbbmqbhcdarzowkkyhiddqs 23X5 9228 Frxsjybldbefsarcbynecdyggx
Xpklorellnmpapqfwkhopkmcoq 31W9 2068 Hsqmgbbuqcljjivswmdkqtbxix
Mvtrrbljptnsnfwzqfjmafadrr 08O5 0963 Uvqhffbsaqxwpqcacehchzvfrk
Mlnozjkpqpxrjxkitzyxacbhhk 60Q8 8897 Tomfgdwdwfcgpxiqvkuytdlcgd
Ultima modifica effettuata da mik_91 28/01/14 8:02
aaa
28/01/14 18:29
quello che non so come si chiama
Parto(male, direi :)) annunciando che non mi sono curato tanto della logica del programma, ma ho solo controllato l'aspetto tecnico.
Comunque...
Ho notato che l'errore avviene nella inserisci_vini_in_array invece che nella inserisci_in_albero_bin, è corretto?
Avviene in quanto tu controlli
if (nodo_p->codice_vino != NULL)

Senza curarti della validità del nodo_p che passi, cambiando la condizione in
if (nodo_p != NULL && nodo_p->codice_vino != NULL) //Forse e dico forse si può anche togliere il nodo_p->codice_vino != NULL) ma non essendomi curato della logica non mi pronuncio

Successivamente utilizzi un contatore, ma a mio avviso dovresti usare un puntatore ad esso, come fai tu l'incremento è "relativo" e andrai quasi certamente a sovrascrivere su una posizione dell'array, per cui la funzione modificata sarà:
void inserisci_vini_in_array(nodo_albero_bin_t *nodo_p,
                             vino_t *vini,
                             int* i)
{
        if (nodo_p != NULL && 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)++;
 
                inserisci_vini_in_array(nodo_p->dx_p,
                                        vini,
                                        i);
        }
}

Chiaramente, se sei d'accordo con quanto detto dovrai modificare la dichiarazione del metodo in maniera opportuna:
void inserisci_vini_in_array(nodo_albero_bin_t *,
                             vino_t [],
                             int*);

E sarà necessario modificare anche la chiamata(nella funzione stampa_vini), per esempio così:
		int contatore = 0;
        /* trasferimento dei vini dall'albero in un array */
        inserisci_vini_in_array(radice_p,
                                vini,
                                &contatore);




PS: Ho notato che il file di input necessita di una riga vuota finale, altrimenti, se l'EOF arriva al termine del campo "luogo", esso viene letto in maniera errata(non gli viene aggiunto il carattere terminatore di stringa). Magari potresti dare un'occhiata anche a questo particolare
Ultima modifica effettuata da quello che non so come si chiama 28/01/14 22:40
aaa