Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    [C] Creazione Lista da file mi crea un nodo in più con valori zero

    Salve a tutti, sto avendo alcuni problemi nella creazione del mio software, in particolare in questo punto:

    codice:
    /*STRUTTURA DEL NODO DELLA LISTA*/
    struct nodo {
    	int mat, mediavoto;
    	char nome[MAX];
    	struct nodo *succ;
    	};
    
    
    
    /*CREAZIONE DELLA LISTA DA FILE*/
    struct nodo *crealista(void){
    	struct nodo *nodo, *testa;
    	testa = NULL;
    	FILE *file = fopen("dist.txt", "r");	/*Apertura del file in modalità Lettura*/
    
    	while(!feof(file)){	/*Fino alla fine del file chiamato "file"*/
    		nodo = malloc(sizeof(struct nodo));	/*Alloca memoria per il nodo*/
    		fscanf(file, "%d %s %d", &nodo-> mat, nodo-> nome, &nodo ->mediavoto);	/*Acquisisce la tripletta di dati*/
    		nodo-> succ = testa;	/*Il puntatore al nodo successivo punterà alla testa*/
    		testa = nodo;	/*La testa sarà il nodo appena creato*/
    	}
    	fclose(file);	/*Chiusura del file*/
    	return(testa);	/*Restituisce il puntatore alla testa della coda*/
    }
    
    
    
    /*STAMPA DELLA LISTA CREATA*/
    void stampa_lista(struct nodo *nodo){
    	while (nodo != NULL){	/*Finchè non arrivo all'ultimo nodo*/
    		printf("Matricola: %d | Nome: %s | Media voto: %d\n", nodo->mat, nodo->nome, nodo->mediavoto);	/*Stampo le triple*/
    		nodo = nodo->succ;	/*Avanzo di nodo*/
    	}
    return;
    }
    Praticamente creo una struttura dati a lista con dei valori che prendo in input da un file chiamato dist.txt. Ora, avviene tutto alla perfezione tranne che alla fine della lista ho un nodo in più, che ovviamente nella stampa, me lo stampa anche, con valori: Matricola: 0 | Nome: | Mediavoto: 0.

    Perchè succede ciò? Ho utilizzato male la funziona feof? O ho sbagliato qualcosa col collegamento dei nodi della lista?

  2. #2
    Utente di HTML.it L'avatar di MrX87
    Registrato dal
    Jun 2007
    Messaggi
    500
    ciao, i nodi della lista dovrebbero essere collegati bene...facendo un inserimento in testa...mentre per quanto riguarda la funzione feof....onestamente non l'ho mai usata....però ti do una soluzione come facevo io di solito in questi casi anche se potrebbe sembrare meno efficiente in quanto dichiaro delle variabili in più di te e devo fare la copia delle variabili....
    codice:
    struct nodo *crealista(){
    	struct nodo *nodo, *testa;
    	testa = NULL;
    	FILE *file = fopen("dist.txt", "r");	/*Apertura del file in modalità Lettura*/
    	char nome[MAX];
    	int mat, media;
    
    	while(fscanf(file, "%d %s %d", &mat, nome, &media) != EOF){	/*Fino alla fine del file chiamato "file"*/
    		nodo = malloc(sizeof(struct nodo));	/*Alloca memoria per il nodo*/
            nodo->mat = mat;
            strcpy(nodo->nome,nome);
            nodo->mediavoto = media;
    		nodo-> succ = testa;	/*Il puntatore al nodo successivo punterà alla testa*/
    		testa = nodo;	/*La testa sarà il nodo appena creato*/
    	}
    	fclose(file);	/*Chiusura del file*/
    	return(testa);	/*Restituisce il puntatore alla testa della coda*/
    }
    intanto provo a dare un'occhiata alla funzione feof e vedo se capisco come funziona....
    se ci sono problemi o dubbi fammi sapere
    "Non può piovere per sempre" Il Corvo
    Forza Vigor!

  3. #3
    Così come l'hai strutturato va egregiamente, solo come hai detto tu hai in gioco piu variabili, ma nulla di che. Ancora non ho ben capito perché tramite "feof" non mi vada comunque.

    Altrimenti ho creato una funzione che dapprima mi conta le righe del file e poi fa un ciclo for (i=0; i <= numero_righe; i++). Come è più conveniente secondo te? Come hai fatto te o in questo modo?

    Forse nel tuo modo è più pulito.

  4. #4
    Utente di HTML.it L'avatar di MrX87
    Registrato dal
    Jun 2007
    Messaggi
    500
    Così come l'hai strutturato va egregiamente, solo come hai detto tu hai in gioco piu variabili, ma nulla di che. Ancora non ho ben capito perché tramite "feof" non mi vada comunque.
    bhà ho provato anche io un pò...ho letto come funziona la feof...ma non ho capito come mai da quel valore nullo alla fine...magari qualcuno più esperto risponderà...

    Altrimenti ho creato una funzione che dapprima mi conta le righe del file e poi fa un ciclo for (i=0; i <= numero_righe; i++). Come è più conveniente secondo te? Come hai fatto te o in questo modo?
    bhè qua secondo me ci possono essere due filoni di pensiero: il primo è se hai un file con un numero molto elevato di righe inizia a diventare poco efficiente...perchè deve leggere due volte il file.
    Inoltre, se utilizzi la funzione che hai detto tu, non è più necessario utilizzare le liste, in quanto conoscendo la dimensione del file con una bella malloc ti allochi il tuo spazio e gestisci il tutto con un vettore di struct, molto più semplice da gestire rispetto ad una lista! ( infatti agli esami della mia università per costringerci ad usare le liste agli esami specificavano che il file andava letto una e una sola volta!).

    Il secondo filone di pensiero, potrebbe trovare la mia soluzione non molto corretta in quanto sei costretto a usare delle variabili di appoggio, anche se alla fine, lo spreco di memoria è limitato....

    Tra le due preferisco la mia soluzione, anche perchè è quella che mi hanno insegnato all'università e che ho sempre usato....poi ognuno ha il suo stile a programmare...

    Spero di essere stato chiaro...se c sono problemi scrivi!
    ciao
    "Non può piovere per sempre" Il Corvo
    Forza Vigor!

  5. #5
    Originariamente inviato da MrX87
    bhà ho provato anche io un pò...ho letto come funziona la feof...ma non ho capito come mai da quel valore nullo alla fine...magari qualcuno più esperto risponderà...


    bhè qua secondo me ci possono essere due filoni di pensiero: il primo è se hai un file con un numero molto elevato di righe inizia a diventare poco efficiente...perchè deve leggere due volte il file.
    Inoltre, se utilizzi la funzione che hai detto tu, non è più necessario utilizzare le liste, in quanto conoscendo la dimensione del file con una bella malloc ti allochi il tuo spazio e gestisci il tutto con un vettore di struct, molto più semplice da gestire rispetto ad una lista! ( infatti agli esami della mia università per costringerci ad usare le liste agli esami specificavano che il file andava letto una e una sola volta!).

    Il secondo filone di pensiero, potrebbe trovare la mia soluzione non molto corretta in quanto sei costretto a usare delle variabili di appoggio, anche se alla fine, lo spreco di memoria è limitato....

    Tra le due preferisco la mia soluzione, anche perchè è quella che mi hanno insegnato all'università e che ho sempre usato....poi ognuno ha il suo stile a programmare...

    Spero di essere stato chiaro...se c sono problemi scrivi!
    ciao
    Forse preferisco la tua soluzione, credo che implementerò quella. Ora se posso...ho un altro piccolo problema nella cancellazione dei nodi. Precisamente nella cancellazione del nodo in testa. Ho provato qualunque metodo di cancellazione della testa ma quando faccio la free non mi cancella nulla.
    Ti passo il codice:
    Codice PHP:
    /*CANCELLAZIONE DI UN NODO*/
    void cancella(struct nodo *nodo){
        
    struct nodo *prec, *temp;    /*Creo il nodo prec che punta al nodo precedente*/
        
    int canctrovato;    /*Variabile per il numero di matricola da cancellare e variabile per controllo matricola esistente*/
        
    trovato 0;
        
        
    printf ("Inserisci la Matricola da cancellare:\n");
        
    scanf ("%d", &canc);
        
        
    temp nodo;
        
    prec NULL;    /*Prec parte da zero, per iniziare lo scorrimento della lista da zero*/
        
        
    while(nodo != NULL){    /*Finchè non arrivo all'ultimo nodo*/
            
    if((nodo-> mat == canc) && (nodo == temp)){    /*Se la matricola del nodo corrente è uguale alla matricola che dobbiamo eliminare ed è in testa*/
                
    nodo nodo-> succ;    /*La testa è il nodo successivo alla testa*/
                
    free(temp);    /*Cancello il nodo temp che è in testa*/
                
    printf ("\nTesta cancellata\n");
                
    temp nodo;    /*La nuova testa è temp, ovvero il nodo successivo alla vecchia testa*/
                
    trovato 1;
                
            }
            else{
                if((
    nodo-> mat == canc) && (nodo != temp)){    
                    
    prec-> succ nodo-> succ;    /*Colleco il nodo precedente col nodo successivo a quello corrente*/
                    
    free(nodo);     /*Cancello il nodo*/   
                    
    nodo prec-> succ;    /*Il nodo corrente diventa il successivo al precedente*/
                    
    printf ("\nMatricola cancellata\n");
                    
    trovato 1;
            
                }
                    else{
                        
    prec nodo;    
                        
    nodo nodo-> succ;    /*Avanzo di nodo*/
                      
    }
              }
              
          }
          
          
          if (
    trovato == 0)    /*Se la matricola non è stata trovata*/
              
    printf ("\nMatricola non trovata\n");
    return;

    Intanto ti ringrazio infinitamente per l'aiuto che mi hai dato fino ad ora, se riesci a darmi un'occhiata anche a questo problema te ne sarei altrettanto grato.

    PS: E' un esercizio per un progetto universitario, con l'obbligo dell'uso delle liste, funziona tutto e sono vicino alla conclusione, l'ultimo bug è proprio questo.

  6. #6
    Utente di HTML.it L'avatar di MrX87
    Registrato dal
    Jun 2007
    Messaggi
    500
    ciao, ho provato un attimo il codice e infatti c'è un problema in testa e questo è dovuto dal fatto che tu modifichi il puntatore alla testa solo nella funzione ma una volta tornato nel main hai il puntatore alla testa iniziale...quindi ti compaiono i vari campi del primo blocco nulli a causa della free effettuata....se invece tu ritorni il puntatore alla testa corretto....dopo le opportune modifiche per la cancellazione, nel main ritorni ad avere il puntatore corretto!

    spero di essermi spiegato...al momento non ho tempo per correggere il codice, però l'errore secondo me è questo...prova a fare qualche correzione tu...se hai problemi scrivimi che magari ti propongo una mia correzione....

    ciao
    "Non può piovere per sempre" Il Corvo
    Forza Vigor!

  7. #7
    Hai ragione te, infatti se dopo aver fatto la modifica ai nodi nella funzione "cancella" e quindi anche dopo aver eliminato la testa invoco una qualsiasi altra funzione di stampa o ordinamento (all'interno della stessa funzione "cancella") mi stampa la lista corretta. Ma ancora non ho capito allora come farla ritornare per poi invocare la funzione semplicemente dal main.

    Ti posto il "nuovo" codice:


    Codice PHP:
    /*CANCELLAZIONE DI UN NODO*/
    struct nodo *cancella(struct nodo *nodo){
        
    struct nodo *prec, *temp;    /*Creo il nodo prec che punta al nodo precedente*/
        
    int canctrovato;    /*Variabile per il numero di matricola da cancellare e variabile per controllo matricola esistente*/
        
    trovato 0;
        
        
    printf ("Inserisci la Matricola da cancellare:\n");
        
    scanf ("%d", &canc);
        
        
    temp nodo;
        
    prec NULL;    /*Prec parte da zero, per iniziare lo scorrimento della lista da zero*/
        
        
    while(nodo != NULL){    /*Finchè non arrivo all'ultimo nodo*/
            
    if((nodo-> mat == canc) && (nodo == temp)){    /*Se la matricola del nodo corrente è uguale alla matricola che dobbiamo eliminare ed è in testa*/
                
    temp nodo-> succ;    /*La testa è il nodo successivo alla testa*/
                
    free(nodo);    /*Cancello il nodo temp che è in testa*/
                
    printf ("\nTesta cancellata\n");
                
    nodo temp;    /*La nuova testa è temp, ovvero il nodo successivo alla vecchia testa*/
                
    trovato 1;
                
    bubblesort(nodo);
                
            }
            else{
                if((
    nodo-> mat == canc) && (nodo != temp)){    
                    
    prec-> succ nodo-> succ;    /*Colleco il nodo precedente col nodo successivo a quello corrente*/
                    
    free(nodo);     /*Cancello il nodo*/   
                    
    nodo prec-> succ;    /*Il nodo corrente diventa il successivo al precedente*/
                    
    printf ("\nMatricola cancellata\n");
                    
    trovato 1;
                    
                }
                else{
                        
    prec nodo;    
                        
    nodo nodo-> succ;    /*Avanzo di nodo*/
                  
    }
              }
              
          }
          
          if (
    trovato == 0)    /*Se la matricola non è stata trovata*/
              
    printf ("\nMatricola non trovata\n");
          
    return(
    nodo);

    Ti ho postato tutto il codice ma in realtà serve solo la prima parte, come puoi vedere dopo la cancellazione della testa (primo if) eseguo la funzione bubblesort() che esegue ordinamento e stampa della lista, in modo corretto!!! Allora perchè quando eseguo il return non mi restituisce la testa corretta? Non ho ben capito la situazione.

    Mi scoccia terribilmente richiederti di nuovo aiuto, una volta fatto ciò però ho finito del tutto! Grazie!

  8. #8
    Ok ci sono riuscito, nella main dovevo semplicemente dire che in effetti:
    testa = cancella(testa);

    E non semplicemente invocare cancella(testa); come fosse una funzione che non ha return tipo la stampa!

    Grazie infinite per i tuoi aiuti!

  9. #9
    Utente di HTML.it L'avatar di MrX87
    Registrato dal
    Jun 2007
    Messaggi
    500
    okok...perfetto....ma io ieri sera ti avevo risposto....non è stato pubblicato il post...mah....sarà comunque si la soluzione è questa...
    "Non può piovere per sempre" Il Corvo
    Forza Vigor!

  10. #10
    Utente di HTML.it
    Registrato dal
    Sep 2011
    Messaggi
    41

    Versione con feof() che non funziona

    Credo che la versione con feof() non funzioni correttamente perché all'esecuzione dell'ultima fscanf() che avviene con successo il flag EOF del file non è ancora settato; ciò invece accade con la successiva chiamata a fscanf() della quale però si recuperano gli elementi in output senza assicurarsi che questi siano stati effettivamente letti (e in effetti non lo sono, essendo alla fine del file!) e di fatto l'inizializzazione del nuovo nodo contiene dati "inconsistenti" (tutto a 0).

    Stefano.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.