[C] Uso delle liste

Pubblicità

Fra01vi

Nuovo Utente
Messaggi
17
Reazioni
0
Punteggio
25
Ciao a tutti,
avrei una domanda probabilmente un po' banale ma non riesco a venirne a capo.
Sto utilizzando delle liste singolarmente concatenate in C.
Vorrei capire come ritornare all'inizio della lista, ovvero inizializzare nuovamente il puntatore all'inizio della lista dopo aver scorso/modificato la lista.
Per spiegarmi meglio: creo la lista, la inizializzo a NULL e inserisco i nodi della lista che mi servono. Dopodichè in base ad alcune condizioni devo eliminare dei nodi della lista, quindi la scorro tutta eliminando quando li trovo i nodi opportuni.
Dopodichè dovrei stampare la lista, ma passando la lista come parametro alla mia funzione "stampa_lista", passo l'elemento NULL che è l'ultimo nodo visitato della lista.
Salvandomi invece, prima di eliminare i nodi della lista, un puntatore alla testa della lista, quando questa viene modificata, il puntatore alla testa della lista punterà ancora alla lista precedente non modificata.
Spero di essermi spiegato in modo decente.
Grazie in anticipo a tutti per la risposta.
 
scrivi prima la funzione stampa lista: deve solo stampare e non deve fare niente altro
scrivi la funzione di eliminazione che non deve fare niente altro
se elimini bene deve funzioanre per forza, se ti stampa tutto signifcia che non hai eliminato bene (tipicamente dimentichi o di aggiornare il puntatore al prossimo elemento del nodo PRECEDENTE a quello eliminato)
 
scrivi prima la funzione stampa lista: deve solo stampare e non deve fare niente altro
scrivi la funzione di eliminazione che non deve fare niente altro
se elimini bene deve funzioanre per forza, se ti stampa tutto signifcia che non hai eliminato bene (tipicamente dimentichi o di aggiornare il puntatore al prossimo elemento del nodo PRECEDENTE a quello eliminato)
la mia lista è fatta in questo modo:
Codice:
typedef struct node
{
    char *p;
    struct node *next;
}node_t;

typedef node_t *Ptr_node;
Questa è la mia funzione di eliminazione. C'è qualcosa che non va? Eseguendo debug step-by-step mi sembra che faccia il suo lavoro.
Codice:
Ptr_node rimuovi_elemento(Ptr_node f, char *s)
{
    int trovato = 0;
    Ptr_node curr, temp, prec;
    prec = NULL;
    curr = f;
    while (!trovato && curr)                
    {
        if (strcmp(s, f->f)==0)                
        {
            trovato = 1;
            temp = curr;                    
            curr = curr->next;            
            if (prec != NULL)
                prec->next = curr;        
            else
                f = curr;
            free(temp);                    
        }
        else
        {
            prec = curr;
            curr = curr->next;
        }
    }
    return f;
}
Il problema è che quel "return f" non mi ritorna la testa della lista, bensì il nodo della lista dopo l'ultimo nodo visitato.
Faccio un esempio: ho questa lista iniziale: ciao->come->stai->tu->?->Io->bene->NULL
Desidero eliminare i nodi contenenti le stringhe "come", "Io". L'eliminazione mi sembra che la faccia in modo corretto, quando poi vado a stamparla il risultato è bene->NULL.
 
if (strcmp(s, f->f)==0)
sono un po' arrugginito... che sarebbe f->f?
intuitivamente farei f->p a guardare la struct
inoltre non ritornerei proprio nulla: l'eliminazione la farei void EDIT: anzi non void ma che ritorni un valore per successo/insuccesso come suggerito da @DispatchCode
 
Ultima modifica:
sono un po' arrugginito... che sarebbe f->f?
intuitivamente farei f->p a guardare la struct
inoltre non ritornerei proprio nulla: l'eliminazione la farei void
Notavo la medesima cosa, non esiste quel membro.

L'eliminazione per coerenza con ciò che accade nella funzione la farei boolean (in C, int, o si include stdbool); true se l'elemento è stato eliminato e false altrimenti (se non lo trova nella lista).

Comunque a prima vista non mi sembra il modo corretto per eliminare (vedo che cambi il valore di f), accertati che funzioni. Da pc guardo meglio.

Cosa molto importante: dai nomi con un senso a quelle variabili. "p" non vuol dire niente, "f" nemmeno. Leggendo il codice dovremmo essere in grado, senza nemmeno avere contesto, di capire cosa contiene quella lista. ?
 
Notavo la medesima cosa, non esiste quel membro.

L'eliminazione per coerenza con ciò che accade nella funzione la farei boolean (in C, int, o si include stdbool); true se l'elemento è stato eliminato e false altrimenti (se non lo trova nella lista).

Comunque a prima vista non mi sembra il modo corretto per eliminare (vedo che cambi il valore di f), accertati che funzioni. Da pc guardo meglio.

Cosa molto importante: dai nomi con un senso a quelle variabili. "p" non vuol dire niente, "f" nemmeno. Leggendo il codice dovremmo essere in grado, senza nemmeno avere contesto, di capire cosa contiene quella lista. ?
Si hai ragione sul fatto dei nomi delle variabili. E' che sono nella fase iniziale e quindi ho dato dei nomi un po' casuali per provare inizialmente solo il funzionamento. Ti ringrazio per la dritta sulla funzione di eliminazione, provo a rendere booleana la funzione
--- i due messaggi sono stati uniti ---
Notavo la medesima cosa, non esiste quel membro.

L'eliminazione per coerenza con ciò che accade nella funzione la farei boolean (in C, int, o si include stdbool); true se l'elemento è stato eliminato e false altrimenti (se non lo trova nella lista).

Comunque a prima vista non mi sembra il modo corretto per eliminare (vedo che cambi il valore di f), accertati che funzioni. Da pc guardo meglio.

Cosa molto importante: dai nomi con un senso a quelle variabili. "p" non vuol dire niente, "f" nemmeno. Leggendo il codice dovremmo essere in grado, senza nemmeno avere contesto, di capire cosa contiene quella lista. ?
Si, nel codice è giusto, qui la struct l'ho fatta in quel momeno dimenticando che l'attributo di tipo char* fosse f e non p.
Ti ringrazio.
 
Se la funziona di eliminazione cancella il primo elemento della lista, ovviamente *deve* ritornare come valore quello della testa (indipendentemente sia modificata o meno). Il problema e' che il tuo codice e' un po pasticciato (il strcmp() e' sbagliato, devi usare curr e non f)
A parte i consigli già dati, ti faccio presente che c'e' un bel memory leak, in quanto liberi la memoria della struttura che elimini, ma non elimini la memoria allocata per il membro 'p'

PS mai "saltare" passi importanti anche nella fase iniziale, specie nei nomi delle variabili con i quali e' facilissimo fare sbagli e scrivere una variabile invece di un'altra (vedi sopra). Tieni presente che una volta che il codice funziona e' difficile tornare indietro e fare modifiche. Sempre iniziare con il piede giusto (chi ha fatto il servizio militare lo sa) Ho scritto una guida a riguardo, la trovi nell'elenco, nelle discussioni in rilievo
 
E pensare che è la funzione di riferimento che mi ha dato la mia prof per l'eliminazione di un elemento dalla lista... :(((
 
Ho provato a cercare un po' anche online, qualche funzione che eliminasse un elemento dalla lista. Qualunque cosa io abbia trovato mi restituisce sempre, non la testa della lista, ma l'elemento successivo a quello eliminato, perdendo così gli elementi prima. Non riesco a capire come devo fare D: D:
Questa ad esempio, fa quello che deve fare, ma non restituisce la testa della lista.
Qualcuno riesce a farmi capire come dovrei fare?
Codice:
Ptr_node rimuovi_elemento(Ptr_node lista, char *elemento) {
    Ptr_node temp;
    Ptr_node p;
    if (lista!=NULL)
        if (!strcmp(lista->stringa, elemento)) {
            temp = lista->next;
            free(lista);
            lista = temp;
        }
        else {
            p = lista;
            while (p->next != NULL) {
                if (strcmp(p->next->stringa, elemento)==0) 
                    p = p->next;
                else 
                    break;
            }
            if (p->next != NULL) {
                temp = p->next->next;
                free(p->next);
                p->next = temp;
            }
        }
    return lista;
}
 
Ciao, ora non ho tempo di guardarmi il codice con calma, ma se posso, ti consiglierei di dividere quella funzione in 3 funzioni elementari: una funzione di tipo void che si limita ad eliminare il nodo passato come argomento, una funzione che scorre la lista (passata come argomento) e restituisce il primo nodo il cui valore sia uguale al target passato come argomento (se non trova nessuna corrispondenza ovviamente ritornerà NULL), infine una terza funzione che sfrutta le due precedenti per eliminare tutte le occorrenze di un certo valore dalla lista.
Inoltre al fine di scrivere codice più conciso sarebbe molto utile sfruttare i puntatori doppi.

Se sei interessato magari provo a spiegarmi meglio.
 
dubito che il tuo ultimo esempio funzioni, in quanto esci dal ciclo while() quando la stringa contenuta nella lista e' diversa dalla stringa passata alla funzione. Devi uscire quando le stringhe sono uguali. Inoltre la rimozione e' sbagliata in quanto liberi la memoria associata alla variabile p->next e poi usi la stessa variabile.
 
Pubblicità
Pubblicità
Indietro
Top