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

    [C] Problema con lista di nodi

    Salve !
    Il professore di linguaggio C ci ha chiesto di completare e correggere un esempio di lista di nodi. Riscontro un problema quando intendo rimuovere il nodo testa, verificandosi un problema di puntatori. Il codice è questo :

    codice:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    
    typedef struct nodolista
    {
      int KEY;
      struct nodolista *next;
    } nodolista;
    
    
    nodolista* aggiungiintesta(int key, nodolista*);
    void visualizzalista(nodolista*);
    void rilascianodo(nodolista*);
    
    
    
    int main()
    {
      nodolista *testa;
      testa = calloc(1, sizeof(nodolista));
      testa = aggiungiintesta(3, testa);
      printf("\n");
      visualizzalista(testa);
      testa = aggiungiintesta(2, testa);
      printf("\n");
      visualizzalista(testa);
      testa = aggiungiintesta(1, testa);
      printf("\n");
      visualizzalista(testa);
      printf("\n");
      rilascianodo(testa);
      visualizzalista(testa);
      
      system("PAUSE");
      return 0;
    }
    
    
    
    nodolista* aggiungiintesta(int key, nodolista *testa)
    {
      nodolista *ptr;
      ptr = calloc(1, sizeof(nodolista));
      
      if(ptr == NULL)
      {
         printf("Memoria insufficiente !\n");
         return NULL;
      }
      
      ptr -> next = testa; //ptr[val|pun ---> testa
      testa = ptr;
      ptr -> KEY = key;
      return ptr;
    }
    
    
    
    void rilascianodo(nodolista* ptr)
    {
      nodolista *p;
      p = calloc(1, sizeof(nodolista));
      
      while(ptr)
      {
        p = ptr -> next;
        free(ptr);
        ptr = p;
      }
    }
    
    
    
    void visualizzalista(nodolista* ptr)
    {
       while(ptr)
       {
       	 printf("[%d]", ptr -> KEY);
       	 if(ptr -> next != NULL)
         	printf(" ---> ");
         ptr = ptr -> next;
       }
    }
    Potete cortesemente aiutarmi a fixare l' errore ?
    Grazie in anticipo !

  2. #2
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    silverfox5010

    non capisco perché hai realizzato la funzione "rilascianodo" in questo modo

    codice:
    void rilascianodo(nodolista* ptr)
    {
      nodolista *p;
      p = calloc(1, sizeof(nodolista));
      
      while(ptr)
      {
        p = ptr -> next;
        free(ptr);
        ptr = p;
      }
    }
    Cioè tu in pratica dichiari un puntatore al nodo della lista locale alla function, gli allochi spazio in memoria e poi...? In pratica è come se ti volessi ricostruire la lista con quel while... o sbaglio? Questa lista che tu crei è locale alla function e non la passi al main.

    Io to consiglio di stutturare la funzione in questo modo

    codice:
    void rilascianodo(nodolista** ptr)
    {
      nodolista *p=*ptr;
      
      *ptr=(*ptr)->next;
      
      free(p);  
    }
    in pratica il puntatore ptr viene passato per riferimento simulato alla function. La chiamata da main a cui devi ricorrere è

    rilascianodo(&testa);

    in pratica devi passare NON il puntatore testa, ma l'indirizzo del puntatore testa, questo perché all'interno della function deve essere modificato il suo valore (è come quando passi ad una funzione un argomento per riferimento, anzi non "è come" è proprio così).

    Nella funzione che ti ho scritto sopra, dichiari un puntatore a nodolista e gli associ il valore di *ptr (ossia di testa nel main) dopodiché a (*ptr) assegni il valore del campo next della testa, in modo che nel main il valore di testa verrà modificato (e risulterà uguale al nodo ad esso successivo) quindi hai appunto eliminato il nodo di testa. La free(p) come ultima istruzione serve per deallocare lo spazio inizialmente occupato da "testa" che ora hai eliminato.

    Ovviamente il prototipo della function deve essere

    void rilascianodo(nodolista**);

    Se apporti queste tre modifiche, vedrai che funziona tutto per bene.

    Forse non sono stato chiarissimo, nel caso chiedi pure

  3. #3
    Grazie ! Funziona alla grande ^^ !
    Ho capito il procedimento da te adoperato. Ma quello che mi
    spaventa è se il prof avesse scritto quel ciclo per mettere in difficoltà
    o perchè prevedesse una ulteriore soluzione lol.
    Grazie per il tuo aiuto utilissimo TT_TT (lacrime di gioia lollollol) !

  4. #4
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    Ma l'ha scritto un professore quel codice? Sicuro di averlo copiato bene? Se è opera di un docente dimmelo che me lo rivedo un po' per cercare di capire dov'è l'errore...

    [OT]Ah comunque ti consiglio di evitare la system("PAUSE"); le chiamate sistem() ricevono argomenti che dipendono dal sistema operativo. system("PAUSE") funziona solo su Windows. So che a te non interessa realizzarere un codice portabile ma è meglio sviluppare fin da subito una certa sensibilità per certi tipi di problemi.

    Come bloccare l'esecuzione di un programma? O con getchar() oppure - come faccio io - con scanf("\n%*c"); che chiede da tastiera un carattere senza assegnarlo a nessuna variabile. Il \n prima serve per evitare problemi di lettura da tastiera nel caso in precedenza ci fossero state altre scanf();[/OT]


    Comunque fammi sapere quel fatto del codice...

  5. #5
    Ho controllato la slide del professore è il codice è quello. Cambia solo il nome della variabile puntatore locale alla funzione :



    codice:
    void rilascia(nodolista *ptr)
    {
      nodolista *app;
      while (ptr) 
      {
        app = ptr->next;
        free(ptr);
        ptr = app;
      }
    }
    Si conoscevo il fatto inerente al system("PAUSE"); che è usato per windows, ma non ero al corrente dell' utilizzo di getchar() o dello scanf("\n%*c"); come sostituti al system("PAUSE");.
    Grazie per le dritte e se trovi la risposta al motivo del codice del prof fammi sapere ^^ !
    Grazie in anticipo !

  6. #6
    Ho notato che nel codice che mi hai suggerito la scorsa volta c'è un passaggio che per come è scritto non sembra influire su *ptr. Assegni il valore di ptr in p, poi assegni il successore di ptr in ptr e liberi la memoria allocata per p, ma in pratica p ha contenuto il valore di ptr all' inizio e poi questo stesso valore è stato cancellato a seguito di free(p);.

    codice:
    void rilascianodo(nodolista** ptr)
    {
      nodolista *p=*ptr;
      
      *ptr=(*ptr)->next;
      
      free(p);  
    }

    Così ho modificato il codice nel seguente modo :
    codice:
    void rilascianodo(nodolista** ptr)
    {
      nodolista *p;
      p =(*ptr)->next;
      free(ptr);
      *ptr = p;  
    }
    Ho dichiarato un puntatore *p, ho assegnato a p il valore del nodo successore al nodo testa, ho liberato la memoria allocata per ptr ed infine ho assegnato p a ptr.

  7. #7
    Originariamente inviato da silverfox5010
    ...
    Così ho modificato il codice nel seguente modo :
    codice:
    void rilascianodo(nodolista** ptr)
    {
      nodolista *p;
      p =(*ptr)->next;
      free(ptr);
      *ptr = p;  
    }
    Ho dichiarato un puntatore *p, ho assegnato il valore del nodo successore al nodo testa a p, ho liberato la memoria allocata per ptr ed infine ho assegnato p a ptr.
    In pratica hai solo 'abbruttito' il codice di YuYevon.
    01010011 01100001 01101101 01110101 01100101 01101100 01100101 01011111 00110111 00110000
    All errors are undocumented features waiting to be discovered.

  8. #8
    Ouch lol !! Già hai proprio ragione. Ho capito adesso il mio errore e il pregio del suo codice lollol !

  9. #9
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    Silverfox5010 in effetti non vedo cosa cambia, anche se a dire il vero quel

    free(ptr);
    *ptr = p;

    non mi piace per nulla percé tu prima deallochi la locazione di memoria puntata da ptr e poi gli assegni un altro valore...

    Cos'ha che non ti piace la funzione che ti ho scritto io?

    ...ma in pratica p ha contenuto il valore di ptr all' inizio e poi questo stesso valore è stato cancellato a seguito di free(p);
    Non ho "cancellato il valore di p" con la free, ho deallocato la memoria puntata da p, che era quella puntata da ptr (ossia la testa della lista) prima del suo "aggiornamento"

    Ah comunque ho rivisto la funzione che originariamente avevi scritto tu (quella col while): sarà che non arrivo a capire ma a me sembra che il suo scopo sia quello di cancellare tutta la lista, come in effetti avviene se poi la vai a stampare...

    Se qualcuno riesce a trovare la ratio di quella cosa... sarei felice di conoscerla

  10. #10
    Grazie per la tua spiegazione TT_TT lol!
    Beh se qualcuno può anche illuminare me sul motivo di quel codice del professore lol. Certe volte mi chiedo se si è davvero laureato. Ad ogni modo lol.

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.