Ci sono diversi pasticci, alcuni ovvi, alcuni subdoli.
1) in stampa() devi inserire un 'printf("\n")' alla fine, altrimenti la riga non viene stampata su schermo. Questo e' un'ottimizzazione inserita penso di recente per poter supportare il print su schermo da parte di piu' thread: la riga viene scritta in blocco solo se termina con un "\n".
Se non sai che cosa e' un thread, non preoccuparti. E' roba per programmatori esperti.
2) elimina(): c'e' troppo codice! Dirai: che centra?, Centra! Perche' fai la stessa cosa in punti diversi della routine ma non nelo stesso modo! Questo ha come conseguenza che se correggi un punto, non e' detto che correggi anche gli altri. Anzi, nel 99.99999% dei casi non succede, con conseguenze devastanti (si e' comnvinti di aver fatto la correzione ma continua a non funzionare)
Ma iniziamo:
2.1) allo startup NON HAI
p=start
last=p
MA
p = start
last = NULL
E' una questione di coerenza, ma anche di codice in meno da scrivere
2.2) questa e' subdola
if(p->dato%2!=0){
if(p==start){
free(start);
start=p->next;
p=start;
}
else
qui hai p==start, MA chiami 'free(start)' e quindi 'start=p->next'.
Ora, poiche' sei partito con 'p==start' e start (e quindi p) e' stato liberato, NON PUOI FARE NESSUN AFFIDAMENTO sul contenuto del blocco di memoria. Da nessuna parte ti viene assicurato che il contenuto della memoria venga mantenuto dopo essere stata rilasciata. E' assolutamente dipendente dall'implementazione della libreria. Nel mio caso, ad esempio, il contenuto della memoria viene sovvrascritto con un pattern. Quindi, PRIMA si accede alle informazioni, POI si libera il nodo
2.3) anche questa e' subdola:
else{
last->next=p->next;
free(p);
if(last->next!=NULL) //altrimenti va in errore
p=last->next;
}
}
last=p;
p=p->next;
Qui' ci sono due errori:
a) a 'p' assegni 'p->next' DUE VOLTE: una dentro l'else ed una all'uscita dell' "if"
b) esegui 'p=p->next' SENZA CONTROLLARE se hai raggiunto la fine della lista
2.4) questo codice non serve a nulla:
if(last->next!=NULL) //altrimenti va in errore
Se ti da errore, non e' mettendoci delle zeppe/accrocchi (alias test inutili) che elimini l'errore, ma capendo PERCHE' va in errore.
In generale la regola che devi seguire e' la seguente: l'algoritmo NON DEVE AVERE codice inutile, DEVE ESSERE COMPATTO ed elegante.