Strutture 'linkate'

di Anonimizzato15457 il
12 risposte
Salve, vi scrivo per sapere se qualcuno di voi mi può aiutare a risolvere un problema riscontrato nella compilazione di un programma in c riguardante le strutture linkate.
struct data
{
  char nome [20];
  struct data *NEXT ; 
};

typedef struct data LISTANOMI ; /* Lista di nomi del tipo */
typedef struct data *LINK ;

LINK head = NULL ; /*Inizio Lista (Head)*/
LINK newelem = NULL ;  /*Nuovo Elemento della Lista (Newelem) */
LINK current = NULL ; /*Posizione corrente nella Lista (Current)*/


/* Funzione per visualizzare la schermta prima di passare alla successiva */

void insertend()
{

  char name[20];

  current = head;

  while (current -> NEXT != NULL)
  {
   current = current -> NEXT;
  }
/* Alloca la casella contente il valore da inserire nella lista */
  newelem=(LINK)malloc(sizeof(LINK));
  current -> NEXT = newelem;
  newelem -> NEXT = NULL;
  printf("\nInserire nome da accodare alla lista: ");
  scanf("%s",name);
  strcpy(newelem -> nome, name);
  printf("\n");

}

void erase()
{
/* Variabile logica inizializzata su falso */
  int trovato=0;

/* Variabile che indica l'elemento da trovare */
  char key[25];

/* Torna ad inizio Lista */
  current = head;

/* Inserisci la chiave di ricerca dell'eliminazione del file */
  printf("\nQuale nome vuoi eliminare?");
  scanf("%s",key);

  do
  {
   if ( strcmp(current -> nome,key) == 0 )
   {
    printf("Eccolo!");
    trovato = 1; 
   }
   current = current -> NEXT;
  } 
  while ((current != NULL) && (trovato == 0));

   if (trovato == 0)
    printf ("\nElemento non trovato!!!");
}

void displaylista ()
{
/* Indice contatore inizializzato a 0 */
  int i=0;

/* Cambia la posizione corrente con la testa, in modo da trovarsi in testa alla lista
*/
  current = head ;

/* Stampa un form a video che contenga la lista */
  printf ("\n" );
  printf ("Lista corrente\n" );

/* Ciclo while che stampa gli elementi della lista */
  while (current != NULL )
  {
/* Contatore che permette la visualizzazione della posizione */
/* di un elemente nella lista
*/
   i++;

/* Stampa a video la posizione dell'elemnto nella lista */
   printf ("%d " ,i);

/* Stampa gli elementi nella lista */
    printf (">    %s\n" , current -> nome );

/* Avanza nella lista */
    current = current -> NEXT ;
   }
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "liste_menu.c" /* Carica le procedure delle funzioni */

main ()
{
  int scelta;

  printf ("Scegli l'operazione da eseguire:\n\n" );
  printf (" 2 - Accoda un elemento nella lista\n" );
  printf (" 3 - Cancella un elemento\n" );
  printf (" 4 - Visualizza la lista \n" );
  printf ("\n" );
  printf ("Scegli: " );
  scanf ("%d" ,&scelta );

  switch (scelta )
  {

   case 2:
    insertend (); /* Inserisci in coda alla lista */
   break ;

   case 3:
     erase (); /* Cancella un elemento dalla lista */
   break ;

   case 4:
    displaylista (); /* Visualizza la lista */
   break ;
  }

return 0;

}
Non riesco ad individuare l'errore, che sicuramente sarà dovuto ad una mal allocazione di memoria o ad un uso non proprio dei puntatori; il messaggio di errore visualizzato è il seguente: "Errore di segmentazione (core dump creato)".
Vi ringrazioe anticipatamente

12 Risposte

  • Il codice completo è quello che hai postato?

    Se così te lo lascia compilare?
  • Si, l'eseguibile viene creato ma quando decido di inserire o di eliminare(operazione impossibile da eseguire essendo vuota) mi da l'errore : "Errore di segmentazione (core dump creato)".
  • Il problema sta nel fatto che i puntatori newelm, current ed head sono null, quindi non puntano a nulla.

    Ad ogni modo, penso debba rivedere la modularità del programma.
    Ho l'impressione che stai cercando di scrivere una libreria; ma la scrivi in maniera anomala nel senso che hai due file ma in realtà è un'unico monoblocco del main, con le variabili e funzioni scritte appunto prima del main, nei fatti non modularizza. (Non lo so se è proprio quello che vuoi)

    Ad ogni modo il segmentation fault è dato dai puntatori NULL che poi li utilizzi subito nelle funzioni, insertend, ecc...
  • Hai ragione per le librerie avrei dovuto creare un'altro file. Invece ho provato ad eliminare l'inizializzazione di LINK head LINK newelem LINK current, ma nonostante la modifica l'errore si ripresenta.
  • Ho anche provato a compattare i due file, ma non riesco a compilare in quanto viene visualizzato questo errore
    a.c:56:6: warning: conflicting types for ‘insertend’ [enabled by default]
     void insertend()
          ^
    a.c:39:5: note: previous implicit declaration of ‘insertend’ was here
         insertend (); /* Inserisci in coda alla lista */
         ^
    a.c:78:6: warning: conflicting types for ‘erase’ [enabled by default]
     void erase()
          ^
    a.c:43:6: note: previous implicit declaration of ‘erase’ was here
          erase (); /* Cancella un elemento dalla lista */
          ^
    a.c:108:6: warning: conflicting types for ‘displaylista’ [enabled by default]
     void displaylista ()
          ^
    a.c:47:5: note: previous implicit declaration of ‘displaylista’ was here
         displaylista (); /* Visualizza la lista */
         ^
    
  • LINK head è un puntatore ad una struttura che non esiste, va prima allocata. Altirmenti non sai come farla puntare ai vari campi.

    Spero averti dato uno spunto.
  • TI ringrazio per i suggerimenti ma penso di non aver capito molto bene il meccanismo... Ho provato ad adattare un programma preesistente modificando il tipo di dato: da int a char.
    #include <stdio.h>
    #include <assert.h>
    #include <stdlib.h>
    #include <string.h>
    #define M 10
    
    struct SInfo {
     
     char utente[M];
    };
    typedef struct SInfo TInfo;
    
    
    struct SNode {
     
     TInfo info;
     struct SNode *link;
    
    };
    
    typedef struct SNode TNode;
    typedef TNode *TList;
    
    TList Crea_Lista();
    
    TList Inserisce_Elemento(TList lista, TInfo info);
    void Stampa_Lista(TList lista);
    
    int main() {
    
     TList lista;
     TInfo info[M];
    
     lista = Crea_Lista();
     
    
     printf("Inserire il nome da aggiungere\n");
     scanf("%s", info->utente);
    
     lista = Inserisci_Elemento(lista,info);
    
     Stampa_Lista(lista);
    
    return 0;
    
    }
    
    TList Crea_Lista() {
     
     return NULL;
    
    }
    
    
    TList Inserisce_Elemento(TList lista, TInfo info) { //
    
     TList newnode;
     newnode = (TNode *)malloc(sizeof(TNode));
     assert(newnode != NULL); 
     newnode->info = info;
     newnode->link = NULL;
     
     return newnode;
    
    }
    
    void Stampa_Lista(TList lista) {
    
     TList curr;
     curr = lista;
    
     while(curr != NULL) {
     
      printf("%s",curr->info.utente);
      curr = curr->link;
     }
    
    }
    
    ma purtropp ottengo questo errore:
    r.c: In function ‘main’:
    r.c:40:8: warning: assignment makes pointer from integer without a cast [enabled by default]
      lista = Inserisci_Elemento(lista,info);
            ^
    /tmp/ccK8SXna.o: nella funzione "main":
    r.c:(.text+0x4a): riferimento non definito a "Inserisci_Elemento"
    collect2: error: ld returned 1 exit status
    
    . Per caso sapresti dirmi come aggiustare il codice in modo da poterlo compilare? Grazie di tutto.
  • Hai necessità di vedere bene l'allocazione dinamica ed approfondire l'uso dei puntatori e il passaggio di parametri alle funzioni.

    Ci sono molte cose che non vanno nel tuo codice.

    Se vuoi che compili, ma continuerà a non funzionare perchè le funzioni non sono scritte correttamente ecco un modo:
    
    int main() {
    
        TList lista;
        TInfo info[M];
        int i=0;
    
        lista = Crea_Lista();
    
        while(i<M) {
            printf("Inserire il nome da aggiungere\n");
            scanf("%s", info->utente);
    
            lista = Inserisce_Elemento(lista,info[i]);
            i++;
        }
        Stampa_Lista(lista);
    
        return 0;
    
    }
    
    Ti consiglio di approfondire i concetti che ti ho detto sopra, sarà difficile adattare programmi scritti se non si è compreso che cosa si vuol fare. Perdonami la shiettezza!

    Se hai difficoltà, posta le specifiche del problema e proverò a darti suggerimenti su cosa implementare e come.

    P.s.
    Hai studiato la modularità? Gli header file? Di solito queste cose si fanno costruendo librerie ad hoc.
  • Non ti preoccupare anzi ti ringrazio, comunque sono argomenti che sto affrontando da poco e non ho molta dimestichezza, anzi.. Comuque ti ringrazio, vedo di ripassare gli argomenti che mi hai consigliato e riprovo a scrivere il codice.
    Grazie.
  • Nonostante abbia perso gran parte della mia credibilità, sono riuscito a tirar fuori un'altro programma, più semplice, che prende dei valori da schermo li mette in lista e poi li stampa.. riesco a creare l'eseguibile, ma non riesco a salvare i valori visto che la stampa avviene senza valori. Sto sbagliando con la memoria dinamica o coi puntatori? o peggio entrambi?
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    
    # define M 10
    
    typedef char element_type;
    
    typedef struct list_element {
    
     element_type value[M];
     struct list_element *next;
    
    } item;
    
    typedef item *list;
    
    void showlist (list l);
    
    int  main(void)
    {
     list root=NULL, aux;
     char n[M];
     int max;
     int i=0;
    
     printf("Inserire max numer oclienti\n");
     scanf("%d", &max);
    
     while (i<max)
     {
      if (root==NULL) 
      {
       root=(list)malloc(sizeof(struct list_element));
       aux=root;
      }
      else
      { 
       aux->next=(list)malloc(sizeof(struct list_element));
       aux=aux->next;
      }
      
      scanf("%s", n);
      strcmp(aux->value,n);
      aux->next = NULL;
      i++;
    }
    
    showlist(root);
    
    return 0;
    }
    
    
    
    void showlist (list l)
    { 
     printf("[");
    
     while (l!=NULL)
     {
      printf("%s",l->value);
      l=l->next;
    
      if (l!=NULL) 
       printf (","); 
     }
       printf("]\n");
    }
    
    
    
    
    Grazie, perdona la mia insistenza.
  • Nel codice che hai postato funziona tutto a patto di sostituire la strcmp con la strcpy.

    strcpy(aux->value,n);

    Vuoi copiare la stringa letta nella lista, non confrontare qualcosa.

    Attento! Non sottovalutare i warning che il compilatore it da.
  • Fantastico grazie mille, comunque strano durante la compilazione non mi da nessun warning. Grazie mille comunque per il tempo.
Devi accedere o registrarti per scrivere nel forum
12 risposte