Salve a tutti, sto cercando di fare un programma in C che legge riga per riga da un file .txt, salva i dati direttamente nei vari nodi, salvandoli all'inizio in ordine di tempo e poi tramite menù a schermo dovrebbe essere possibile all'utente decidere quale valore cercare all'interno dell'albero. In questa parte faccio una copia dell'albero di partenza riorganizzando l'ordine dell'albero a seconda del tipo indicato (tempo, gas o elettricità), cancello il vecchio albero e salvo la vecchia sentinella dandole l'indirizzo del nuovo albero copiato.
Il problema è che a tempo di copmilazione dà segmentation fault quando prova a fare il ripristino dell'equilibrio e non riesco a capirne il motivo. So che il segmentation fault è dato quando viene seguito un puntatore nullo ma non riesco a capire quale puntatore è nullo né perchè, neanche usando il debugger. Qualcuno riesce a capire che cosa sto sbagliando? Allego il codice qui sotto:
/*DIRETTIVE AL PREPROCESSORE*/
#include<stdio.h>
#include<stdlib.h> //serve per malloc
#define bool int
#define true 1
#define false 0
/*DEFINIZIONE DEI TIPI*/
typedef enum {rosso, nero} colore_t;
//definizione del tipo di struttura nodo
typedef struct nodo_albero_bin_rn
{
int tempo;
double gas,
elettricita;
colore_t colore;
struct nodo_albero_bin_rn *sx, //collegamento a nodo sinistro
*dx, //collegamento a nodo destro
*padre; //collegamento al nodo padre
} nodo_albero_bin_rn_t;
/*DICHIARAZIONE DELLE FUNZIONI*/
int scelta_operazione(void);
void pulisci_buffer(void);
int inserisci_in_albero_bin_ric_rn(nodo_albero_bin_rn_t *sent_p, int tem, double g, double elet);
void ripristina_ins_albero_bin_ric_rn(nodo_albero_bin_rn_t *sent_p, nodo_albero_bin_rn_t *nodo_p);
void ruota_sx(nodo_albero_bin_rn_t *sent_p, nodo_albero_bin_rn_t *x_p);
void ruota_dx(nodo_albero_bin_rn_t *sent_p, nodo_albero_bin_rn_t *x_p);
void visita_albero_bin_simm(nodo_albero_bin_rn_t *nodo_p, nodo_albero_bin_rn_t *sent_p);
void cerca_valore(nodo_albero_bin_rn_t *sent_p, double valore, int *tipo_p);
void copia_albero_bin_post(nodo_albero_bin_rn_t *nodo_p, nodo_albero_bin_rn_t *sent_vecchia, nodo_albero_bin_rn_t *sent_nuova, int *tipo_p);
int inserisci_nuovo(nodo_albero_bin_rn_t *sent_vecchia, nodo_albero_bin_rn_t *sent_nuova, int *tipo_p);
void cancella_albero(nodo_albero_bin_rn_t *sent_p, nodo_albero_bin_rn_t *sent_nuova);
void cancella_nodi_post(nodo_albero_bin_rn_t *nodo_p, nodo_albero_bin_rn_t *sent_p);
/*DEFINIZIONE DELLE FUNZIONI*/
// Funzione main
int main(int argc, const char * argv[]) {
int tipo = 1, //input: tipo di valore da cercare
*tipo_p = &tipo, //input: puntatore a tipo
scelta, //lavoro: operazione scelta
ins, //lavoro: operazione andata a buon fine di inserimento nodo
tem; //lavoro: proprieta' tempo del nodo
double valore, //input: valore da cercare
g, //lavoro: proprieta' gas del nodo
elet; //lavoro: proprieta' elettricità del nodo
//lavoro: radice albero principale
nodo_albero_bin_rn_t *sent_p = NULL;
sent_p = (nodo_albero_bin_rn_t *)malloc(sizeof(nodo_albero_bin_rn_t));
sent_p->sx = sent_p->dx = sent_p;
sent_p->colore = nero;
sent_p->padre = NULL;
//lavoro: radice albero copia
nodo_albero_bin_rn_t *sent_nuova = NULL;
sent_nuova = (nodo_albero_bin_rn_t *)malloc(sizeof(nodo_albero_bin_rn_t));
sent_nuova->sx = sent_nuova->dx = sent_nuova;
sent_nuova->colore = nero;
sent_nuova->padre = NULL;
//apertura file per acquisizione dati
FILE *file_dati = fopen("dati_riscaldamento.txt","r");
if (file_dati==NULL)
{
printf("Questo file non esiste.\n");
}
else
{
//dichiaro che i parametri del nuovo nodo creato devono avere valori uguali a quelli letti dal file
while (fscanf(file_dati, "%d %lf %lf",
&tem, &g, &elet)
!= EOF)
{
//funzione di inserimento dei nodi
ins = inserisci_in_albero_bin_ric_rn(sent_p, tem, g, elet);
/* if (ins==0)
printf("Duplicate found!\n"); */
}//end of while
}//end fopen
//chiusura file acquisizione dati
fclose(file_dati);
printf("Tempo\t\tGas\t\t\tElettricita'\n");
visita_albero_bin_simm(sent_p->sx,sent_p);
printf("Dati caricati correttamente dal file\n");
do
{
/* Stampiamo il menu delle scelte */
scelta = scelta_operazione();
switch (scelta)
{
case 1:
/* Cerca i dati relativi a una determianta rilevazione */
printf("Scegli il parametro da cercare:\n 1.Tempo 2.Gas 3.Elettricita'\n");
scanf("%d", &tipo);
printf("Inserisci il valore da cercare\n"
"(es. di formati di ricerca: tempo - aaaammgghh, gas - 0.0, elettricita' - 0.0):\n");
scanf("%lf", &valore);
copia_albero_bin_post(sent_p->sx, sent_p, sent_nuova, &tipo);
cancella_albero(sent_p, sent_nuova);
cerca_valore(sent_p, valore, &tipo);
break;
/*
case 2:
//da fare
Cancella i dati corrispondenti a una determinata rilevazione
printf("Scegli il parametro da cancellare:\n 1.Tempo 2.Gas 3.Elettricita'\n");
scanf("%d", &tipo);
printf("Inserisci il valore da cercare:\n");
scanf("%lf", &valore);
cerca_valore(sent_p, valore, &tipo);
//funzione di rimozione
break;
default:
return 0;
break; */
}
} while (scelta != 2);
return 0;
}//end main
// Altre funzioni
// Funzione che stampa il menu
int scelta_operazione(void)
{
/* Definizione delle variabili locali relative alla funzione */
bool esito_operazione = true; /* lavoro: esisto operazioni funzione */
int scelta, /* input: operazione da eseguire */
esito_lettura; /* lavoro: esito lettura scanf */
do
{
esito_operazione = true;
printf("\nScegliere se si vuole:\n");
printf("[1] Cercare e stampare i dati relativi a una determinata rilevazione\n");
printf("[2] Cancellare i dati relativi a una determinata rilevazione\n");
printf("[3] Uscire\n");
esito_lettura = scanf("%d", &scelta);
/* Svuotiamo il buffer da eventuali caratteri in eccesso */
pulisci_buffer();
if (esito_lettura != 1 || scelta < 1 || scelta > 3)
{
printf("Errore: inserire un numero da 1 a 3.\n");
esito_operazione = false;
}
} while (!esito_operazione);
return scelta;
}//end scelta_operazione
// Funzione che pulisce il buffer di stdin
void pulisci_buffer(void)
{
/* Definizione delle variabili locali relative alla funzione */
char carattere_rimosso; /* lavoro: variabile pulitura buffer input */
do
{
carattere_rimosso = getchar();
} while (carattere_rimosso != '\n');
}
int inserisci_in_albero_bin_ric_rn(nodo_albero_bin_rn_t *sent_p, int tempo, double gas, double elettricita) {
int inserito;
nodo_albero_bin_rn_t *nodo_p, *padre, *nuovo_p;
for(nodo_p = sent_p->sx, padre = sent_p;
((nodo_p != sent_p) && (nodo_p->tempo != tempo));
padre = nodo_p, nodo_p = (tempo < nodo_p->tempo)? nodo_p->sx:nodo_p->dx)
;
if(nodo_p != sent_p)
inserito = 0;
else {
inserito = 1;
nuovo_p = (nodo_albero_bin_rn_t *)malloc(sizeof(nodo_albero_bin_rn_t));
nuovo_p->tempo = tempo;
nuovo_p->gas = gas;
nuovo_p->elettricita = elettricita;
nuovo_p->colore = rosso;
nuovo_p->sx = nuovo_p->dx = sent_p;
nuovo_p->padre = padre;
if(padre == sent_p) {
sent_p->sx = sent_p->dx = nuovo_p;
} else {
if(tempo < padre->tempo)
padre->sx = nuovo_p;
else
padre->dx = nuovo_p;
}
ripristina_ins_albero_bin_ric_rn(sent_p, nuovo_p);
}
return(inserito);
}
void ripristina_ins_albero_bin_ric_rn(nodo_albero_bin_rn_t *sent_p,
nodo_albero_bin_rn_t *nodo_p) {
nodo_albero_bin_rn_t *zio_p;
while(nodo_p->padre->colore == rosso) {
if (nodo_p->padre == nodo_p->padre->padre->sx) {
zio_p = nodo_p->padre->padre->dx;
if (zio_p->colore == rosso) {
nodo_p->padre->colore = nero;
zio_p->colore = nero;
nodo_p->padre->padre->colore = rosso;
nodo_p = nodo_p->padre->padre;
}
else {
if (nodo_p == nodo_p->padre->dx) {
nodo_p = nodo_p->padre;
ruota_sx(sent_p, nodo_p);
}
}
nodo_p->padre->colore = nero;
nodo_p->padre->padre->colore = rosso;
ruota_dx(sent_p, nodo_p->padre->padre);
}
else {
zio_p = nodo_p->padre->padre->sx;
if (zio_p->colore == rosso) {
nodo_p->padre->colore = nero;
zio_p->colore = nero;
nodo_p->padre->padre->colore = rosso;
nodo_p = nodo_p->padre->padre;
}
else {
if (nodo_p == nodo_p->padre->sx) {
nodo_p = nodo_p->padre;
ruota_dx(sent_p, nodo_p);
}
}
nodo_p->padre->colore = nero;
nodo_p->padre->padre->colore = rosso;
ruota_sx(sent_p, nodo_p->padre->padre);
}
}
sent_p->sx->colore = nero;
}//end ripristina_ins_albero_bin_ric_rn
void ruota_sx(nodo_albero_bin_rn_t *sent_p, nodo_albero_bin_rn_t *x_p) {
nodo_albero_bin_rn_t *y_p;
y_p = x_p->dx;
x_p->dx = y_p->sx;
if (y_p->sx != sent_p)
y_p->sx->padre = x_p;
y_p->padre = x_p->padre;
if(x_p == sent_p->sx) {
sent_p->sx = sent_p->dx = y_p;
}
else {
if(x_p == x_p->padre->sx) {
x_p->padre->sx =y_p;
}
else {
x_p->padre->dx = y_p;
}
}
y_p->sx = x_p;
x_p->padre = y_p;
}//end ruota_sx
void ruota_dx(nodo_albero_bin_rn_t *sent_p, nodo_albero_bin_rn_t *x_p) {
nodo_albero_bin_rn_t *y_p;
y_p = x_p->sx;
x_p->sx = y_p->dx;
if (y_p->dx != sent_p)
y_p->dx->padre = x_p;
y_p->padre = x_p->padre;
if(x_p == sent_p->dx) {
sent_p->dx = sent_p->sx = y_p;
}
else {
if(x_p == x_p->padre->dx) {
x_p->padre->dx =y_p;
}
else {
x_p->padre->sx = y_p;
}
}
y_p->dx = x_p;
x_p->padre = y_p;
}//end ruota_dx
void visita_albero_bin_simm(nodo_albero_bin_rn_t *nodo_p, nodo_albero_bin_rn_t *sent_p) {
if (nodo_p != sent_p) {
visita_albero_bin_simm(nodo_p->sx, sent_p);
printf("%d\t\t\t%.2f\t\t\t\t%.2f\n",
nodo_p->tempo,
nodo_p->gas,
nodo_p->elettricita);
visita_albero_bin_simm(nodo_p->dx, sent_p);
}
}//end visita_albero_bin_simm
// cerca un valore
void cerca_valore(nodo_albero_bin_rn_t *sent_p, double valore, int *tipo_p)
{
nodo_albero_bin_rn_t *nodo_p;
if(*tipo_p == 1)
{
valore = (int) valore;
for (nodo_p = sent_p->sx;
nodo_p != sent_p && nodo_p->tempo != valore;
nodo_p = (valore < nodo_p->tempo)? nodo_p->sx : nodo_p->dx)
;
}
else if(*tipo_p == 2)
{
for (nodo_p = sent_p->sx;
nodo_p != sent_p && nodo_p->gas != valore;
nodo_p = (valore < nodo_p->gas)? nodo_p->sx : nodo_p->dx)
;
}
else if(*tipo_p == 3)
{
for (nodo_p = sent_p->sx;
nodo_p != sent_p && nodo_p->elettricita != valore;
nodo_p = (valore < nodo_p->elettricita)? nodo_p->sx : nodo_p->dx)
;
}
else {
printf("Numero inserito sbagliato, si prega di riprovare.\n");
return;
}
{
if(nodo_p == sent_p) //se non trova l'elemento cercato fino alla fine
{
printf("L'elemento cercato non è presente nella rilevazione.\n");
return; //esce dalla funzione
}
else
{
printf("Tempo\t\t\t\tGas\t\t\t\tElettricita'\n");
printf("%d\t\t%.2f\t\t%.2f\n",
nodo_p->tempo,
nodo_p->gas,
nodo_p->elettricita);
}
}
}//end cerca_valore
//chiamato in originale con sent_p->sx e sent_p
void copia_albero_bin_post(nodo_albero_bin_rn_t *nodo_p, nodo_albero_bin_rn_t *sent_vecchia, nodo_albero_bin_rn_t *sent_nuova, int *tipo_p)
{
if (nodo_p != sent_vecchia) {
copia_albero_bin_post(nodo_p->sx, sent_vecchia, sent_nuova, tipo_p);
copia_albero_bin_post(nodo_p->dx, sent_vecchia, sent_nuova, tipo_p);
inserisci_nuovo(nodo_p, sent_nuova, tipo_p);
}
}//end copia_albero_bin_post
int inserisci_nuovo(nodo_albero_bin_rn_t *sent_vecchia, nodo_albero_bin_rn_t *sent_nuova, int *tipo_p)
{
int inserito;
nodo_albero_bin_rn_t *nodo_p = NULL, *padre, *nuovo_p;
if(*tipo_p == 1)
{
for(nodo_p = sent_nuova->sx, padre = sent_nuova;
((nodo_p != sent_nuova) && (nodo_p->tempo != sent_nuova->tempo));
padre = nodo_p, nodo_p = (sent_nuova->tempo < nodo_p->tempo)? nodo_p->sx:nodo_p->dx)
;
}
else if(*tipo_p == 2)
{
for(nodo_p = sent_nuova->sx, padre = sent_nuova;
((nodo_p != sent_nuova) && (nodo_p->gas != sent_nuova->gas));
padre = nodo_p, nodo_p = (sent_nuova->gas < nodo_p->gas)? nodo_p->sx:nodo_p->dx)
;
}
else if(*tipo_p == 3)
{
for(nodo_p = sent_nuova->sx, padre = sent_nuova;
((nodo_p != sent_nuova) && (nodo_p->elettricita != sent_nuova->elettricita));
padre = nodo_p, nodo_p = (sent_nuova->elettricita < nodo_p->elettricita)? nodo_p->sx:nodo_p->dx)
;
}
if(nodo_p != sent_nuova)
inserito = 0;
else {
inserito = 1;
nuovo_p = (nodo_albero_bin_rn_t *)malloc(sizeof(nodo_albero_bin_rn_t));
nuovo_p->tempo = sent_vecchia->tempo;
nuovo_p->gas = sent_vecchia->gas;
nuovo_p->elettricita = sent_vecchia->elettricita;
nuovo_p->colore = rosso;
nuovo_p->sx = nuovo_p->dx = sent_nuova;
nuovo_p->padre = padre;
if(padre == sent_nuova) {
sent_nuova->sx = sent_nuova->dx = nuovo_p;
} else {
if(*tipo_p == 1)
{
if(nuovo_p->tempo < padre->tempo)
padre->sx = nuovo_p;
else
padre->dx = nuovo_p;
}
else if(*tipo_p == 2)
{
if(nuovo_p->gas < padre->gas)
padre->sx = nuovo_p;
else
padre->dx = nuovo_p;
}
else if(*tipo_p == 3)
{
if(nuovo_p->elettricita < padre->elettricita)
padre->sx = nuovo_p;
else
padre->dx = nuovo_p;
}
}
ripristina_ins_albero_bin_ric_rn(sent_nuova, nuovo_p);
}
return(inserito);
}//end inserisci_nuovo
void cancella_albero(nodo_albero_bin_rn_t *sent_p, nodo_albero_bin_rn_t *sent_nuova)
{
cancella_nodi_post(sent_p->sx, sent_p);
sent_p = sent_nuova;
visita_albero_bin_simm(sent_p->sx,sent_p);
free(sent_nuova);
}
void cancella_nodi_post(nodo_albero_bin_rn_t *nodo_p, nodo_albero_bin_rn_t *sent_p)
{
if (nodo_p != sent_p) {
cancella_nodi_post(nodo_p->sx, sent_p);
cancella_nodi_post(nodo_p->dx, sent_p);
free(nodo_p);
}
}//end cancella_nodi_post
Il file .txt contiene queste righe (int double double):
2019042908 1.3 2.70
2019042909 0.3 4.26
2019042910 8.3 5.14
2019042911 9.2 7.00
2019042912 7.1 4.56
2019042913 6.0 5.78
2019042914 5.6 3.02