Creazione e stampa lista in C

di il
3 risposte

Creazione e stampa lista in C

Ciao a tutti, sono un programmatore in erba (anzi, erbissima direi).
Ho iniziato da poco le liste in C e sto cercando di allenarmi su di esse (con risultati non ottimi ).
Oggi ho provato, per vedere se i concetti base li ho digeriti, a creare una lista con interi inseriti da tastiera (0 per terminare) e successivamente stamparla. Evidentemente qualcosa non mi è ancora chiaro (spero non troppe cose).
Se riusciste a indirizzarmi verso i miei errori ve ne sarei grato


P.S: Mi da' il segmentation fault
P.P.S: Se ci sono errori grossolani non vi arrabbiate, trattatemi come un principiante perchè è quello che sono (Mi preparo ad una shitstorm )
struct Struttura
{
  int info;
  struct Struttura *next;
};

int ChiediValore()
{
  int val;
  printf("\nInserire un intero\n");
  scanf("%d", &val);
  return val;
}

typedef struct Struttura Ciao;

Ciao* CreaLista()
{
  Ciao *head;
  Ciao *punt = (Ciao*)malloc(sizeof(Ciao));
  ChiediValore();
  if(ChiediValore != 0)
  {
    punt->info = ChiediValore();
    head = punt;
    punt = punt->next;
  }
  else
  {
    head->next = NULL;
  }
  
  ChiediValore();
  while(ChiediValore() != 0)
  { 
    punt->info = ChiediValore();
    punt->next = head;
    head = punt;
    ChiediValore();
  }
  return head; 
}

void StampaLista(Ciao *head)
{
  Ciao *temp = head;
  while(temp->next != NULL)
    {
      printf("%d\n", temp->info);
      temp = temp->next;
    }
}

int main()
{
  CreaLista();
  StampaLista(CreaLista());
}

3 Risposte

  • Re: Creazione e stampa lista in C

    Gentile Tannush,
    ho riscritto la funzione per la creazione della lista,
    perche' la tua mi e' parsa poco chiara.

    Ci sono anche altri modi per implementarla.

    Confrontandola con la tua potrai capire cosa non andava
    e se/come puoi modificare CreaLista() per farla funzionare bene.

    Comunque, secondo me e' meglio separare l'inserimento dei dati
    da parte dell'utente dall'inserimento dei dati in lista.

    Nei miei programmi preferisco soluzioni del tipo:
    
    funzione crea_lista()
    {
       ciclo di chiamate alle 2 funzioni: 
       v = ChiediValore()
       metti_in_lista_il_valore(v)
    }
    

    Ho introdotto modifiche nelle altre funzioni.

    Quando si chiama una funzione (non void) bisogna assegnarne il valore di uscita
    a una variabile, salvo i casi tipo if (funzione())...
    
    /*  LISTA.C  */
    
    # include <stdio.h>
    # include <stdlib.h>
    
    struct Struttura
    {
      int info;
      struct Struttura *next;
    };
    
    typedef struct Struttura Ciao;
    
    int   ChiediValore();
    Ciao  *crea_lista();
    Ciao* CreaLista();
    void  StampaLista(Ciao *head);
    
    /* ----------------------------------------------------------- */
    
    int main()
    {
       // puntatore alla prima struct della lista
       Ciao *p = NULL;
    
       printf("\n%s\n", "-----------------------------------------------------------");
       printf("\n%s\n\n", "INSERIMENTO NUMERI INTERI IN LISTA");
    
    //  p = CreaLista();
      p = crea_lista();
      StampaLista(p);
      printf("\n%s\n", "-----------------------------------------------------------");
    }
    /* --------------------------------------------------------------------------- */
    
    int ChiediValore()
    {
      int val;
      printf("%s", "Inserire un intero:  ");
      scanf("%d", &val);
      return val;
    }
    
    
    // creazione di lista di numeri interi, inseriti dall'utente; 
    // rende in uscita il valore del puntatore al primo elemento della lista; 
    // il valore 0 serve solo per indicare che l'inserimento e' terminato, 
    // ma non viene messo in lista
    Ciao *crea_lista()
    {
      // puntatore al primo elemento della lista
      Ciao *head = NULL;
      // puntatore all'ultimo elemento della lista
      Ciao *ultimo = NULL;
      // puntatore per nuova struct Ciao
      Ciao *punt;
      // uscita della funzione ChiediValore()
      int v;
    
      do
      {
         // assegna a v il numero inserito dall'utente
         v = ChiediValore();
    
         // se il valore inserito e' diverso da 0...
         if (v != 0)
         {
            //...alloca memoria per la nuova struct
            punt = malloc(sizeof(Ciao));
    
            // a questo punto si dovrebbe anche verificare che l'allocazione 
            // sia riuscita, cioe' che il puntatore non sia NULL; 
            // ometto per semplificare
    
            // assegna il valore inserito al relativo campo
            punt->info = v;
            // la nuova struct viene messa all'ultimo posto, 
            // quindi deve puntare a NULL
            punt->next = NULL;
    
            // se la nuova struct e' la prima...
            if (head == NULL)
            {
               // ...il puntatore di inizio lista 
               // deve puntare alla nuova struct
               head = punt;
               // anche il puntatore di fine lista deve 
               // puntare alla nuova struct
               ultimo = punt;
            }
            // altrimenti...
            else
            {
               // ...la struct inserita al passo precedente 
               // deve puntare alla nuova struct
               ultimo->next = punt;
               // la struct appena inserita deve diventare la nuova ultima
               ultimo = punt;
            }
         }   // fine if (v != 0)
    
      }
      while (v != 0);
    
      return head;
    
    }   // fine crea_lista()
    
    // ci sono troppe chiamate di ChiediValore();
    // mancano commenti esplicativi
    Ciao* CreaLista()
    {
      Ciao *head;
      Ciao *punt = (Ciao*)malloc(sizeof(Ciao));  // l'allocazione e' inutile, 
                                                 // se l'utente inserisce solo 0 
                                                 // e la lista rimane vuota
    
      ChiediValore();   // non assegna a nessuna variabile l'output della funzione
    
      if(ChiediValore != 0)  // confronta un puntatore a funzione con 0
      {
        punt->info = ChiediValore();
        head = punt;
        punt = punt->next;
      }
      else
      {
        head->next = NULL;
      }
     
      ChiediValore();   // non assegna a nessuna variabile l'output della funzione
      while(ChiediValore() != 0)
      {
        punt->info = ChiediValore();
        punt->next = head;
        head = punt;
        ChiediValore();  // non serve
      }
      return head;
    }
    
    void StampaLista(Ciao *head)
    {
      Ciao *temp = head;
    
      if (temp == NULL)
      {
        printf("\n%s\n", "Lista vuota");
      }
      else
      {
        printf("\n%s\n", "Lista:");
        //  while(temp->next != NULL)
        while (temp != NULL)
        {
          printf("%d\n", temp->info);
          temp = temp->next;
        }
      }
    }
    /* ------------------------------- FINE LISTA.C ------------------------------ */
    
  • Re: Creazione e stampa lista in C

    Korr ha scritto:


    Gentile Tannush,
    ho riscritto la funzione per la creazione della lista,
    perche' la tua mi e' parsa poco chiara.

    Ci sono anche altri modi per implementarla.

    Confrontandola con la tua potrai capire cosa non andava
    e se/come puoi modificare CreaLista() per farla funzionare bene.

    Comunque, secondo me e' meglio separare l'inserimento dei dati
    da parte dell'utente dall'inserimento dei dati in lista.

    Nei miei programmi preferisco soluzioni del tipo:
    
    funzione crea_lista()
    {
       ciclo di chiamate alle 2 funzioni: 
       v = ChiediValore()
       metti_in_lista_il_valore(v)
    }
    

    Ho introdotto modifiche nelle altre funzioni.

    Quando si chiama una funzione (non void) bisogna assegnarne il valore di uscita
    a una variabile, salvo i casi tipo if (funzione())...

    ......
    Le tue annotazioni sono tutte giuste, mi sento in dovere di segnalarti che, in C, dichiarare funzioni a cui non vano passati parametri senza dichiarale void è un'obsolescenza del C, ancora pruima che fosse standardizzato con lo standard C89.

    Può essere fonte di inumerevoli problemi di sicurezza del codice, quindi in definitiva:
    int funzione()
    deve sempre essere dichiarata come
    int function(void)
    Per darti un rifermineto allo standard C11
    6.11.6 Function declarators
    1 The use of function declarators with empty parentheses (not prototype-format parameter
    type declarators) is an obsolescent feature.
  • Re: Creazione e stampa lista in C

    Grazie per il consiglio, LPs.
    Penso che sara' meglio adeguare i miei programmi a quanto da te affermato,
    cioe' inserire "void" per indicare espressamente che una funzione
    non riceve parametri.
Devi accedere o registrarti per scrivere nel forum
3 risposte