Liste con cancellazione
Devo svolgere un esercizio in cui una volta inserito degli elementi in una lista(ho supposto che vengano inseriti dall'inizio del nodo) devo cancellare i numeri pari inseriti .Questo è il codice ma durante l'esecuzione va in loop:
#include <stdio.h> #include<stdlib.h> /*variabili esterne*/ struct node{ /*come è fatto il nodo*/ int value; struct node * next; }; struct node *first=NULL;/*first punta al primo elemento*/ /*dichiarazione funzioni*/ struct node *read_numbers(void); struct node *add_to_list(struct node *list,int n); void delede_pari(struct node *list); void visualizza_lista(struct node *list); int main(void) { read_numbers(); delede_pari(first); visualizza_lista(first); return 0; } struct node *read_numbers(void) { int n; printf("Inserisci una serie di interi(termina con 0):\n"); for(;;) { scanf("%d",&n); if (n==0) return first; first= add_to_list(first,n);/*aggiungi in cima alla lista*/ } } struct node *add_to_list(struct node *list,int n) { struct node *new_node; /*punto al nuovo nodo*/ new_node=malloc(sizeof(struct node)); if(new_node== NULL) { printf("Error:malloc failed in add_to_list\n"); exit(EXIT_FAILURE); } new_node ->value=n; new_node->next=list; return new_node; } void delede_pari(struct node *list) { struct node *cur,*prev for(cur=list,prev=NULL; cur!=NULL ; prev=cur,cur=cur->next); { if((cur->value)%2==0) { if (cur ==NULL) ; else if (prev==NULL) list=list->next; else prev->next=cur->next; free(cur);/*cancello cur*/ } } } void visualizza_lista(struct node *list) { struct node *q; for(q=list;q!=NULL;q=q->next) printf("%d\n",q->value); }
Risposte
Il TAG per inserire il codice è "code", non "quote". Ti ho modificato il post in modo da usare quello corretto. Il codice lo devo ancora guardare.
Grazie per la correzione
Il problema è che c'è un punto e virgola dopo il for in delede_pari che causa un ciclo infinito. Non è comunque quello l'unico errore del programma. Per esempio non credo sia una bella idea di mischiare funzioni che agiscono su variabili globali e funzioni che agiscono sugli argomenti ad esse passate. Inoltre c'è un problema nel passaggio degli argomenti. Vengono infatti passati per valore mentre sembrerebbe necessario passare gli argomenti per riferimento o usare il valore di ritorno. Insomma, ci sono diverse cose da rivedere nel codice. Ci sto dando un occhiata, ma ti consiglio di provare a correggertelo tu.
infatti il problema non è quello perchè pur correggendolo mi da problemi.
Credo sia la cancellazione perchè quando non inserisco pari va tutto bene se li inserisco va in loop ma non capisco cosa sbaglio.
Credo sia la cancellazione perchè quando non inserisco pari va tutto bene se li inserisco va in loop ma non capisco cosa sbaglio.
Nel mio posto ho già dato diversi spunti su cose che non vanno molto bene. Il mio primo consiglio è quello di rendere le funzioni completamente indipendenti dal resto del programma in modo che agiscano solo su quello che gli viene passato come parametro. Ovviamente potresti fare tutto lavorando sulla variabile globale, ma rendi solo il codice più complicato e in pratica non scriverai mai una lista (o qualsiasi altra classe di questo tipo) usando variabili globali in questo modo. E' quindi molto più istruttivo fare le cose nel modo corretto.
Dopodiché prova a descrivere a parole quello che il tuo codice dovrebbe fare per cancellare i numeri pari. Verifica che il procedimento funzioni quando la lista è vuota, composta da un solo elemento pari, in cui il primo elemento sia pari, in cui l'ultimo elemento sia pari e in cui l'elemento pari sia in mezzo alla lista.
Dopodiché prova a descrivere a parole quello che il tuo codice dovrebbe fare per cancellare i numeri pari. Verifica che il procedimento funzioni quando la lista è vuota, composta da un solo elemento pari, in cui il primo elemento sia pari, in cui l'ultimo elemento sia pari e in cui l'elemento pari sia in mezzo alla lista.
Ho provato a fare come dici ma mi sembra che stia bene il procedimento ho pure provato a cambiare un pò la funzione cancella pari ma continua a non andare.Ho anche provato a fare i disegnini con le liste
però non riesco ancora a trovare l'errore.

void delede_from_list(struct node *list,int n) { struct node *cur=list; struct node *prev=NULL; while(cur!=NULL) { if((cur->value)%2==0) { if (cur ==NULL) break; if (prev ==NULL) list=list->next; else prev->next=cur->next; free(cur); /*libero nodo*/ } prev=cur; cur=cur->next; } }
Per prima cosa, come mi sembra di averti già detto, DEVI restituire qualcosa oppure passare un puntatore a puntatore a nodo. In caso contrario la funzione non sarà mai in grado di gestire i casi in cui il nodo di testa cambi.
intendi così?
struct node *delede_from_list(struct node *list) { struct node *cur=list; struct node *prev=NULL; while(cur!=NULL) { if((cur->value)%2==0) { if (cur ==NULL) break; if (prev ==NULL) list=list->next; else prev->next=cur->next; free(cur); /*libero nodo*/ } prev=cur; cur=cur->next; } return list; }
Allora...
All'interno del ciclo fare il test:
prima di averlo cambiato è inutile. In pratica controlli due volte di fila se è NULL.
Il resto è comunque pensato male. Perché liberi cur e lo usi subito dopo senza essegnarlo.
Vediamo di schematizzare la cosa nel caso non iniziale.
Tu hai che
nel caso in cui
allora devi avere:
oppure anche
se preferisci. In generale dipende da come riunisci il tutto alla fine.
nel caso in cui
dovrai solo spostare in avanti i puntatori:
Vediamo ora il caso iniziale.
Nel caso in cui
allora non hai problemi, devi solo spostare in avanti i puntatori come prima.
Nel caso in cui
dovrai eliminare list.
Questo significa che dovrai fare le seguenti cose:
mentre prev rimarrà NULL.
All'interno del ciclo fare il test:
if (cur == NULL) break;
prima di averlo cambiato è inutile. In pratica controlli due volte di fila se è NULL.
Il resto è comunque pensato male. Perché liberi cur e lo usi subito dopo senza essegnarlo.
Vediamo di schematizzare la cosa nel caso non iniziale.
Tu hai che
prev->next = cur;
nel caso in cui
(cur->value)%2 == 0
allora devi avere:
cur = cur->next; free(prev.next); prev->next = cur;
oppure anche
prev->next; = cur->next; free(cur); cur = prev->next;
se preferisci. In generale dipende da come riunisci il tutto alla fine.
nel caso in cui
(cur->value)%2 != 0
dovrai solo spostare in avanti i puntatori:
prev = cur; cur = cur->next;
Vediamo ora il caso iniziale.
Nel caso in cui
(list->value)%2 != 0
allora non hai problemi, devi solo spostare in avanti i puntatori come prima.
Nel caso in cui
(list->value)%2 != 0
dovrai eliminare list.
Questo significa che dovrai fare le seguenti cose:
cur = cur->next; free(list); list = cur;
mentre prev rimarrà NULL.
Grazie!
Ora però se voglio "complicare" le cose con una lista bidirezionale...supponiamo di fare solo la funzione di lettura e inserimento degli elementi:
Anche in questo caso va in loop però non posso dire che è l'errore di prima perchè qui non c'è cancellazione ma solo un semplice inserimento.
Ora però se voglio "complicare" le cose con una lista bidirezionale...supponiamo di fare solo la funzione di lettura e inserimento degli elementi:
void read_numbers(void) { printf("Inserisci interi.Termina con 0"); for(;;) { struct node *cur ,*prev, *new_node; new_node=malloc(sizeof(struct node));/* crea nuovo nodo*/ if(new_node==NULL) { printf("Database is full;can't add more parts\n"); return; } printf("\nInserisci:"); scanf("%d",&new_node->value); if(new_node->value ==0) { free(new_node); return ; } for(cur=first,prev=NULL; cur!=NULL && new_node->value > cur->value; prev=cur,cur=cur->next) ; /*si ferma quando new_node è inferiore di cur->value*/ if(cur!=NULL && new_node->value == cur->value) { printf("Elemento esiste gia'\n"); free(new_node); return; } if (prev==NULL) { new_node->prec=NULL; new_node->next=first; first->prec=new_node; first=new_node; } else { new_node->next=prev->next; new_node->prec=prev; cur->prec=new_node; prev->next=new_node; } } }
Anche in questo caso va in loop però non posso dire che è l'errore di prima perchè qui non c'è cancellazione ma solo un semplice inserimento.