Visualizzazione dei risultati da 1 a 6 su 6

Discussione: [C] Caricamento lista ordinata da file

  1. #1
    Utente di HTML.it
    Registrato dal
    Aug 2011
    Messaggi
    144

    [C] Caricamento lista ordinata da file

    Ciao ragazzi,
    dispongo di un file di testo contenente alcune informazioni(codice prodotto, codice categoria, descrizione, numero, costo) su 3 prodotti cosi fatto:
    codice:
    A451XXCAT001
    PASTA CONF. 1KG
    100
    99.0
    A451XY
    CAT002
    MAGLIA LANA
    25
    6.70
    A452XX
    CAT001
    SUGO
    33
    9.99
    Devo scrivere una funzione che dopo aver letto ciascun prodotto dal file, lo memorizzi in una lista ordinata mediante il codice prodotto. Tale funzione è la seguente:

    codice:
    int carica_lista(char fName[], listaP *l) {	tipoBaseLista prodotto;
    	int n = 0;
    	char buf[D] = {0};
    	listaP pCorrente; /* puntatore usato per la scansione   */
    	listaP pNodo; /* puntatore di servizio temporaneo   */
    	listaP pPrec; //puntatore al nodo precedente
    	FILE *f; 
    	f = fopen(fName, "r");
    	if (f == NULL) {
    		printf("Non e' possibile aprire il file\n");
    		exit(1);
    	}
    	
    	pNodo = malloc(sizeof(prodotto));
    	pCorrente = NULL;
    	//Per leggere una riga per volta dal file basta usare la funzione fget. Mentre invece, con la funzione sscanf formatto la riga in base al tipo di dato.
    	while (!feof(f)) {
    		printf("\nInizio while %d\n", n+1);
    		fgets(buf, sizeof(buf), f);
    		strcpy(prodotto.codP, buf);
    		fgets(buf, sizeof(buf), f);
    		strcpy(prodotto.codC, buf);
    		fgets(buf, sizeof(buf), f);
    		strcpy(prodotto.descr, buf);
    		fgets(buf, sizeof(buf), f);//lettura del numero dei prodotti
    		sscanf(buf, "%d", &prodotto.num);
    		fgets(buf, sizeof(buf), f);//lettura del costo del prodotto
    		sscanf(buf, "%f", &prodotto.costo);
    
    
    		pNodo->info = prodotto;
    		pNodo->next = NULL;
    		  
    		/* scansione della lista*/
    		if (*l == NULL){//Se la lista è vuota
    			printf("\nEntrato1\n");
    			*l = pNodo;
    		}
    			
    		else if(strcmp(prodotto.codP, (*l)->info.codP) < 0){//se il nuovo nodo deve diventare il nodo testa
    			printf("\nEntrato2\n");
    			pNodo->next = *l; //salvo il vecchio nodo testa
    			*l = pNodo; //valorizzo il nodo testa con il nuovo nodo inserito
    			(*l)->next = pNodo; //collego il nuovo nodo testa con il vecchio
    		}
    		
    		else{//se il nuovo nodo deve essere inserito dopo il nodo testa
    			printf("\nEntrato3\n");
    			pCorrente = *l; //inizializzo il nodo che serve per la scansione con il nodo testa.
    			/*NEL SECONDO CICLO WHILE pCORRENTE PUNTA AL SECONDO PRODOTTO INSERITO. PERCHE'??*/
    			
    			while (pCorrente->next != NULL && strcmp(prodotto.codP, pCorrente->info.codP) > 0){//scansiono la lista finchè il nodo corrente punta ad un elemento non NULL e finchè il prodotto da inserire non ha un codice prodotto inferiore a quello del nodo corrente
    				printf("\nEntrato4\n");
    				pPrec = pCorrente;
    				pCorrente = pCorrente->next;//assegno a pCorrente il riferimento del nodo successivo
    			}
    			/* concatenazione del nuovo record */
    			if(strcmp(prodotto.codP, pCorrente->info.codP) < 0){//inserimento non in coda alla lista
    				printf("\nEntrato5\n");
    				pNodo->next = pCorrente;//collegamento tra il nuovo nodo e il suo successivo
    				pPrec->next = pNodo;//collegamento tra il nodo precedente e quello nuovo
    			}
    			else if(pCorrente->next == NULL) {//inserimento in coda alla lista
    				printf("\nEntrato6\n");
    				pCorrente->next = pNodo;//collegamento della coda della lista al nuovo nodo
    			}
    		}
    		printf("\nFine while %d\n", n+1);
    		n++;
    	}
    	
    		fclose(f);
    		return n;
    		system("PAUSE");
    }
    Tale funzione presenta un'anomalia nell'else commentato con "se il nuovo nodo deve essere inserito dopo il nodo testa": nel secondo ciclo while, pCorrente (e quindi anche il nodo testa l), dopo essere stato inizializzato con il nodo testa (pCorrente = *l, assume erroneamente il valore del secondo prodotto. Dopo svariate letture del codice non sono riuscito a capire qual è la causa del problema .

    Per completezza posto pure la struttura della lista:

    codice:
    typedef struct {	char codP[C];
    	char codC[C];
    	char descr[D];
    	int num;
    	float costo;
    } tipoBaseLista;
    
    
    typedef struct nodoLista{
    	tipoBaseLista info;
    	struct nodoLista *next;
    }prodotto;
    typedef prodotto *listaP;
    e il main
    codice:
    int main() {	char filename[] = "Magazzino.txt";
    	listaP lista = NULL;//Creo una lista vuota
    	printf("\nNumero prodotti caricati: %d\n", carica_lista(filename, &lista));		
    	return 0;
    	system("PAUSE");
    }
    Qualcuno mi potrebbe aiutare?

    Grazie in anticipo,
    mbistato

  2. #2
    Utente di HTML.it
    Registrato dal
    Aug 2011
    Messaggi
    144
    Rettifico il contenuto del file:
    codice:
    A451XX
    CAT001
    PASTA CONF. 1KG
    100
    99.0
    A451XY
    CAT002
    MAGLIA LANA
    25
    6.70
    A452XX
    CAT001
    SUGO
    33
    9.99

  3. #3
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,549
    codice:
                 pNodo->next = *l; //salvo il vecchio nodo testa
                *l = pNodo; //valorizzo il nodo testa con il nuovo nodo inserito
                (*l)->next = pNodo; //collego il nuovo nodo testa con il vecchio
    Stai creando un ciclo: pNodo punterà sempre e solo a pNodo e perderai il resto della lista.
    codice:
                if(strcmp(prodotto.codP, pCorrente->info.codP) < 0){//inserimento non in coda alla lista
    Non è vero perché tecnicamente potrebbe essere <= (anche se non nel tuo caso)

    Puoi cambiare questo blocco di codice
    codice:
    while (pCorrente->next != NULL && strcmp(prodotto.codP, pCorrente->info.codP) > 0){//scansiono la lista finchè il nodo corrente punta ad un elemento non NULL e finchè il prodotto da inserire non ha un codice prodotto inferiore a quello del nodo corrente
                    printf("\nEntrato4\n");
                    pPrec = pCorrente;
                    pCorrente = pCorrente->next;//assegno a pCorrente il riferimento del nodo successivo
                }
                /* concatenazione del nuovo record */
                if(strcmp(prodotto.codP, pCorrente->info.codP) < 0){//inserimento non in coda alla lista
                    printf("\nEntrato5\n");
                    pNodo->next = pCorrente;//collegamento tra il nuovo nodo e il suo successivo
                    pPrec->next = pNodo;//collegamento tra il nodo precedente e quello nuovo
                }
                else if(pCorrente->next == NULL) {//inserimento in coda alla lista
                    printf("\nEntrato6\n");
                    pCorrente->next = pNodo;//collegamento della coda della lista al nuovo nodo
                }
    con questo molto più semplice
    codice:
    while (pCorrente != NULL && strcmp(prodotto.codP, pCorrente->info.codP) > 0){
                    pPrec = pCorrente;
                    pCorrente = pCorrente->next;//assegno a pCorrente il riferimento del nodo successivo
                }
                pNodo->next = pCorrente;//collegamento tra il nuovo nodo e il suo successivo
                pPrec->next = pNodo;//collegamento tra il nodo precedente e quello nuovo
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

  4. #4
    Utente di HTML.it
    Registrato dal
    Aug 2011
    Messaggi
    144
    Ciao Scara95 e grazie per aver risposto.


    Quote Originariamente inviata da Scara95 Visualizza il messaggio
    codice:
                 pNodo->next = *l; //salvo il vecchio nodo testa
                *l = pNodo; //valorizzo il nodo testa con il nuovo nodo inserito
                (*l)->next = pNodo; //collego il nuovo nodo testa con il vecchio
    Stai creando un ciclo: pNodo punterà sempre e solo a pNodo e perderai il resto della lista.

    Su questo pezzo di codice non mi sono soffermato perchè nel mio caso non viene mai eseguito. Se ho capito correttamente, stai dicendo che con l'istruzione *l = pNodo perderò il riferimento del puntatore testa, il quale invece punterà a pNodo, dico bene?
    Ma allora posso correggere scrivendo


    codice:
    pNodo->next = *l;
    (*l)->info = prodotto;
    (*l)->next = pNodo;

    ?


    Per il resto è tutto chiaro.
    Ultima modifica di mbistato; 02-01-2018 a 11:45

  5. #5
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,549
    No, sto dicendo che pNodo->next punterà a pNodo e quindi creerai un ciclo infinito.
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

  6. #6
    Utente di HTML.it
    Registrato dal
    Aug 2011
    Messaggi
    144
    Ho sostituito questo codice
    codice:
    pNodo->next = *l; //salvo il vecchio nodo testa
    *l = pNodo; //valorizzo il nodo testa con il nuovo nodo inserito
    			(*l)->next = pNodo;//collego il nuovo nodo testa con il vecchio
    con questo

    codice:
    pNodo->next = *l;
    (*l)->info = prodotto;
    (*l)->next = pNodo;
    Inoltre, apportando le altre modifiche da te suggerite il programma va in crash al secondo ciclo while e pCorrente non viene correttamente inizializzato con il nodo testa tramite l'istruzione pCorrente = *l;

Tag per questa discussione

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 © 2018 vBulletin Solutions, Inc. All rights reserved.