Problema con lista lineare

di il
28 risposte

Problema con lista lineare

Ragazzi devo creare questa lista lineare completa di menù per inserimento, eliminazione e visualizzazione della lista. Per ora ho implementato l'inserimento in testa e la visualizzazione, ma mi danno dei problemi. Provando col debbagger è come se la function dell'inserimento in testo non aggiornasse i puntatori dopo aver inserito l'elemento...vi passo il codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct persona{
              char nome[20];
              struct persona *p_next;} Persona;


void insl_testa(char [] , Persona **);
void insl_nodo(char [] , Persona **);
void print_lista(Persona *);
void main ()
{
    int op, menu=100;
    Persona *head, *punt;
    char dato[20];
   head=NULL;//creiamo la lista
  while (menu<=100){
  puts("\n\n\n=======================");
puts("GESTIONE DI UNA LISTA");
puts("=======================\n\n");
puts("Selezionare l'operazione:\n");
puts("1=Visualizzare la lista");
puts("2=Inserire un elemento");
puts("3=eliminare un elemento");
scanf("%d",&op);

switch (op) {
case 1: print_lista(&head); break;
case 2 :     printf("Inserie il nuovo nome: ");scanf("%s",dato);
             insl_testa(dato,&head);
         /*else {
             printf("Inserie il nuovo nome: ");scanf("%s",dato);
            insl_nodo(dato,&punt);} break;*/

    }
  }
}
void insl_testa (char dato[20], Persona **p_head)
{
    Persona *ptr;
    ptr=calloc(1,sizeof(Persona));//allochiamo memoria per il nuovo nodo
    ptr->nome[20]=dato[20];//assegna alla nuova memoria allocata il nuovo nodo
    ptr->p_next=*p_head;//il puntatore successivo assume il valore di quello di testa (cioè il punt di testa non è più di testa)
    *p_head=ptr;//aggiorniamo head al nuovo nodo, il nuovo nodo diventa puntato dal puntatore di testa
}
void insl_nodo(char dato[20], struct persona **p_punt)
{
    struct persona *ptr;
    ptr=calloc(1,sizeof(struct persona));
    ptr->nome[20]=dato[20];
    ptr->p_next=(*p_punt)->p_next;
    (*p_punt)->p_next=ptr;
    *p_punt=ptr;
}
void print_lista(Persona *pl)
{
    printf("\n\n");
    printf("lista: ");
    while (pl){
        printf("%s\n", pl->nome[20]);
        pl = pl->p_next;
            }
    printf("\n\n");
}

28 Risposte

  • Re: Problema con lista lineare

    Questo:
    
    ptr->nome[20]=dato[20];
    
    Non fa ciò che tu credi. Esiste la funzione strcpy per fare ciò che intendi fare.

    Questo è da cambiare
    
    printf("%s\n", pl->nome[20]);
    
    printf accetta una stringa non un carattere in una posizione inesistente. nome[20] è fuori dall'indice dell'array che va da 0 a 19. Insomma devi leggere un pò di più sui char array e come funzionano.
  • Re: Problema con lista lineare

    No infatti mi sono accorto anche io di questo errore, ora ho fatto due struct così posso usare '=' come assegnazione
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    typedef struct info{
                    char nome[20];} Info;
    typedef struct persona{
                  Info info;
                  struct persona *p_next;} Persona;
    
    
    void insl_testa(Info , Persona **);
    void insl_nodo(char [] , Persona **);
    void print_lista(Persona *);
    void main ()
    {
        int op, menu=100;
        Persona *head, *punt;
        Info dato;
       head=NULL;//creiamo la lista
      while (menu<=100){
      puts("\n\n\n=======================");
    puts("GESTIONE DI UNA LISTA");
    puts("=======================\n\n");
    puts("Selezionare l'operazione:\n");
    puts("1=Visualizzare la lista");
    puts("2=Inserire un elemento");
    puts("3=eliminare un elemento");
    scanf("%d",&op);
    
    switch (op) {
    case 1: print_lista(&head); break;
    case 2 :     printf("Inserie il nuovo nome: ");scanf("%s",dato.nome);
                 insl_testa(dato,&head); break;
             /*else {
                 printf("Inserie il nuovo nome: ");scanf("%s",dato);
                insl_nodo(dato,&punt);} break;*/
    
        }
      }
    }
    void insl_testa (Info dato, Persona **p_head)
    {
        Persona *ptr;
        ptr=calloc(1,sizeof(Persona));//allochiamo memoria per il nuovo nodo
        ptr->info=dato;//assegna alla nuova memoria allocata il nuovo nodo
        ptr->p_next=*p_head;//il puntatore successivo assume il valore di quello di testa (cioè il punt di testa non è più di testa)
        *p_head=ptr;//aggiorniamo head al nuovo nodo, il nuovo nodo diventa puntato dal puntatore di testa
    }
    /*void insl_nodo(char dato[20], struct persona **p_punt)
    {
        struct persona *ptr;
        ptr=calloc(1,sizeof(struct persona));
        ptr->nome[20]=dato[20];
        ptr->p_next=(*p_punt)->p_next;
        (*p_punt)->p_next=ptr;
        *p_punt=ptr;
    }*/
    void print_lista(Persona *pl)
    {
        printf("\n\n");
        printf("lista: ");
        while (pl){
            printf("%s\n", pl->info);
            pl = pl->p_next;
                }
        printf("\n\n");
    }
    solo che ho ancora problemi quando stampo la lista...mi stampa solo l'ultimo nome che ho inserito e poi subito dopo <null>
  • Re: Problema con lista lineare

    Non complicare le cose non ti serve una seconda struct. basta strcpy
    
    strcpy(ptr->nome,dato);
    
  • Re: Problema con lista lineare

    Ecco il tuo primo programma corretto.
    
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        typedef struct persona{
                      char nome[20];
                      struct persona *p_next;} Persona;
    
    
        void insl_testa(char [] , Persona **);
        void insl_nodo(char [] , Persona **);
        void print_lista(Persona *);
        void main ()
        {
            int op, menu=100;
            Persona *head, *punt;
            char dato[20];
           head=NULL;//creiamo la lista
          while (menu<=100){
          puts("\n\n\n=======================");
        puts("GESTIONE DI UNA LISTA");
        puts("=======================\n\n");
        puts("Selezionare l'operazione:\n");
        puts("1=Visualizzare la lista");
        puts("2=Inserire un elemento");
        puts("3=eliminare un elemento");
        scanf("%d",&op);
    
        switch (op) {
        case 1: print_lista(&head); break;
        case 2 :     printf("Inserie il nuovo nome: ");scanf("%s",dato);
                     insl_testa(dato,&head);
                 /*else {
                     printf("Inserie il nuovo nome: ");scanf("%s",dato);
                    insl_nodo(dato,&punt);} break;*/
    
            }
          }
        }
        void insl_testa (char dato[20], Persona **p_head)
        {
            Persona *ptr;
            ptr=calloc(1,sizeof(Persona));//allochiamo memoria per il nuovo nodo
            strcpy(ptr->nome,dato);//assegna alla nuova memoria allocata il nuovo nodo
            ptr->p_next=*p_head;//il puntatore successivo assume il valore di quello di testa (cioè il punt di testa non è più di testa)
            *p_head=ptr;//aggiorniamo head al nuovo nodo, il nuovo nodo diventa puntato dal puntatore di testa
        }
        void insl_nodo(char dato[20], struct persona **p_punt)
        {
            struct persona *ptr;
            ptr=calloc(1,sizeof(struct persona));
            strcpy(ptr->nome,dato);
            ptr->p_next=(*p_punt)->p_next;
            (*p_punt)->p_next=ptr;
            *p_punt=ptr;
        }
        void print_lista(Persona *pl)
        {
            printf("\n\n");
            printf("lista: ");
            while (pl){
                printf("%s\n", pl->nome);
                pl = pl->p_next;
                    }
            printf("\n\n");
        }
    
  • Re: Problema con lista lineare

    No perchè dopo devo aggiungerci anche l'età e quindi mi servono due struct, solo che all'inizio non volevo complicare e cose ed ho messo solo il parametro nome

    EDIT= cmq anche con il programma che mi hai corretto tu ho sempre problemi con la funzione che stampa la lista
  • Re: Problema con lista lineare

    Beh non ti basta questo:
    
    typedef struct persona{
                      char nome[20];
                      char cognome[20];
                      int eta;
                      struct persona *p_next;} Persona;
    
  • Re: Problema con lista lineare

    Si ma ho cmq problemi nella funzione che stampa la lista
    e poi se faccio due struct nella funzione posso fare un unica assegnazione per l'intero nodo contenente le informazioni, invece così dovrei fare più assegnazioni
  • Re: Problema con lista lineare

    Perche chiami le funzioni in modo sbagliato. Non puoi fare + assegnazioni di un intero nodo almeno che non crei dinamicamente ogni volta il nodo nuovo. Cmq prova il tuo metodo e te ne accorgerai che ogni cella avrà li stessi valori.
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    typedef struct persona{
    			  char nome[20];
    			  struct persona *p_next;} Persona;
    
    
    void insl_testa(char [] , Persona **);
    void insl_nodo(char [] , Persona **);
    void print_lista(Persona *);
    void main ()
    {
    	int op, menu=100;
    	Persona *head, *punt;
    	char dato[20];
    	head=NULL;//creiamo la lista
    
    	while (menu<=100)
    	{
    		puts("\n\n\n=======================");
    		puts("GESTIONE DI UNA LISTA");
    		puts("=======================\n\n");
    		puts("Selezionare l'operazione:\n");
    		puts("1=Visualizzare la lista");
    		puts("2=Inserire un elemento");
    		puts("3=eliminare un elemento");
    		scanf("%d",&op);
    
    		switch (op) 
    		{
    			case 1: print_lista(head); break;
    			case 2 :     
    			{
    					printf("Inserie il nuovo nome: ");scanf("%s",dato);
    					insl_testa(dato,&head);
    			}
    			break;
    		 }
    	}
    }
    void insl_testa (char dato[20], Persona **p_head)
    {
    	Persona *ptr;
    	ptr=calloc(1,sizeof(Persona));//allochiamo memoria per il nuovo nodo
    	strcpy(ptr->nome,dato);//assegna alla nuova memoria allocata il nuovo nodo
    	ptr->p_next=*p_head;//il puntatore successivo assume il valore di quello di testa (cioè il punt di testa non è più di testa)
    	*p_head=ptr;//aggiorniamo head al nuovo nodo, il nuovo nodo diventa puntato dal puntatore di testa
    }
    void insl_nodo(char dato[20], struct persona **p_punt)
    {
    	struct persona *ptr;
    	ptr=calloc(1,sizeof(struct persona));
    	strcpy(ptr->nome,dato);
    	ptr->p_next=(*p_punt)->p_next;
    	(*p_punt)->p_next=ptr;
    	*p_punt=ptr;
    }
    void print_lista(Persona *pl)
    {
    	printf("\n\n");
    	printf("lista: ");
    	while (pl){
    		printf("%s\n", pl->nome);
    		pl = pl->p_next;
    			}
    	printf("\n\n");
    }
    
  • Re: Problema con lista lineare

    Si così và, ora ho provato ad aggiungere inserimento al nodo corrente aggiungendo un if nel case 2, così:
    if (head==NULL){
                        printf("Inserie il nuovo nome: ");scanf("%s",dato);
                        insl_testa(dato,&head); break;}
                    else{
                        printf("Inserie il nuovo nome: ");scanf("%s",dato);
                        insl_nodo(dato,&punt); break;}
    però il programma crasha

    EDIT:
    ora ho aggiunto il campo eta, ma mi crasha quando faccio la scanf per prendere l'età...non capisco proprio perchè
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    typedef struct persona{
               char nome[20];
               short eta;
               struct persona *p_next;} Persona;
    
    
    void insl_testa(char [] , short , Persona **);
    void insl_nodo(char [] , short, Persona **);
    void print_lista(Persona *);
    void main ()
    {
       int op, menu=100;
       Persona *head, *punt;
       char dato_n[20]; short dato_e;
       head=NULL;//creiamo la lista
    
       while (menu<=100)
       {
          puts("\n\n\n=======================");
          puts("GESTIONE DI UNA LISTA");
          puts("=======================\n\n");
          puts("Selezionare l'operazione:\n");
          puts("1=Visualizzare la lista");
          puts("2=Inserire un elemento");
          puts("3=eliminare un elemento");
          scanf("%d",&op);
    
          switch (op)
          {
             case 1: print_lista(head); break;
    
             case 2 :if (head==NULL){
                        printf("Inserie il nuovo nome: ");scanf("%s",dato_n);
                        printf("Inserie l'eta': ");scanf("%d",dato_e);
                        insl_testa(dato_n,dato_e,&head); break;}
                    else{
                        printf("Inserie il nuovo nome: ");scanf("%s",dato_n);
                        printf("Inserie l'eta': ");scanf("%d",dato_e);
                        insl_nodo(dato_n,dato_e,&punt); break;}
           }
       }
    }
    void insl_testa (char dato_n[20], short dato_e, Persona **p_head)
    {
       Persona *ptr;
       ptr=calloc(1,sizeof(Persona));//allochiamo memoria per il nuovo nodo
       strcpy(ptr->nome,dato_n);//assegna alla nuova memoria allocata il nuovo nodo
       ptr->eta=dato_e;
       ptr->p_next=*p_head;//il puntatore successivo assume il valore di quello di testa (cioè il punt di testa non è più di testa)
       *p_head=ptr;//aggiorniamo head al nuovo nodo, il nuovo nodo diventa puntato dal puntatore di testa
    }
    void insl_nodo(char dato_n[20], short dato_e, struct persona **p_punt)
    {
       struct persona *ptr;
       ptr=calloc(1,sizeof(struct persona));
       strcpy(ptr->nome,dato_n);
       ptr->eta=dato_e;
       ptr->p_next=(*p_punt)->p_next;
       (*p_punt)->p_next=ptr;
       *p_punt=ptr;
    }
    void print_lista(Persona *pl)
    {
       printf("\n\n");
       printf("lista: \n");
       while (pl){
          printf("%s\n", pl->nome);
          pl = pl->p_next;
             }
       printf("\n\n");
    }
    
    
  • Re: Problema con lista lineare

    Cos'è punt?
  • Re: Problema con lista lineare

    Punt dovrebbe essere il puntatore al nodo corrente ed head quello alla testa della lista
  • Re: Problema con lista lineare

    Se punt non è iniziliazzato dove credi che questa riga va a leggere
    
    ptr->p_next=(*p_punt)->p_next;
    
    ed ecco il tuo crash.
  • Re: Problema con lista lineare

    Come devo fare per inizializzarlo? cioè all'inizio la lista è vuota ed inizializzo head=NULL, devo inizializzare anche punt=NULL, così che poi quando la funzione aggiorna i puntatori me lo ritrovo alla posizione corrente??
  • Re: Problema con lista lineare

    Devi avere le idee chiare. head sai già cos'è. punt io non ho capito a cosa ti serve. Se vuoi fare un inserimento in mezzo allora può servire. Se vuoi fare un inserimento in testa o in coda non ti serve. Per inserimento in mezzo intendo un inserimento in una lista ordinata. Usa carta e penna e i tuoi dubbi saranno chiariti. quando fai un inserimento in mezzo prima devi trovare il posto giusto (che non hai trovato ancora nel tuo codice) e fermarti una posizione prima del nodo che vai a spingere a destra per far spazio al nuovo nodo. a sto punto puoi fare:
    
    sia ptr il nodo nuovo
    sia punt un posto prima il nodo da spingere a destra.
    ptr->next = punt->next;
    punt->next = ptr;
    
    così hai fatto spazio per il nuovo nodo e tutto funziona.
Devi accedere o registrarti per scrivere nel forum
28 risposte