Piccolo problema con le liste..
Salve , ho un piccolo problema con una lista...Una volta che visualizzo a video i valori che ho inserito , mi visualizza SOLO l'ultimo elemento inserito tante volte quanti sono gli elementi della lista.
Invece questo sono i metodo per inserire e visualizzare i valori :
typedef char* tipoelem; typedef class cella * posizione; class cella { public: cella(); bool operator<(cella &); void setElemento(tipoelem); tipoelem getElemento() const; void setSucc(posizione); void setPrec(posizione); posizione getSucc() const; posizione getPrec() const; private: tipoelem etichetta; posizione successivo; posizione precedente; };
cella::cella() { precedente = successivo = NULL ; etichetta = ""; } ; void cella::setElemento(tipoelem a) { etichetta = a; } tipoelem cella::getElemento() const { return etichetta; } void cella::setPrec(posizione p) { precedente = p; } posizione cella::getPrec() const { return precedente; } void cella::setSucc(posizione p) { successivo = p; } posizione cella::getSucc() const { return successivo; } bool cella::operator<(cella & C2) { if ( getElemento() < C2.getElemento() ) return true; else return false; }
class lista { public: lista(); void creaLista(); bool listaVuota(); bool fineLista(posizione) const; tipoelem leggiLista(posizione) const; void scriviLista(tipoelem,posizione); posizione primoLista() const; posizione succLista(posizione) const; posizione predLista(posizione) const; void insLista(tipoelem , posizione & ); void cancLista(posizione &); private: posizione LISTA; };
lista::lista() { creaLista();} void lista::creaLista() { LISTA = new cella; LISTA->setElemento(NULL); LISTA->setPrec(LISTA); LISTA->setSucc(LISTA); } bool lista::listaVuota() { if ( (LISTA->getSucc()== LISTA) && (LISTA->getPrec()== LISTA )) return true; else return false; } bool lista::fineLista(posizione p) const { return ( p == LISTA ); } tipoelem lista::leggiLista(posizione p) const { return p->getElemento(); } void lista::scriviLista(tipoelem a , posizione p) { p->setElemento(a); } posizione lista::primoLista() const { return LISTA->getSucc(); } posizione lista::succLista(posizione p) const { return p->getSucc(); } posizione lista::predLista(posizione p) const { return p->getPrec(); } void lista::insLista(tipoelem a , posizione & p ) { posizione temp; temp = new cella; temp->setElemento(a); temp->setPrec(p->getPrec()); temp->setSucc(p); (p->getPrec())->setSucc(temp); p->setPrec(temp); p = temp; } void lista::cancLista(posizione & p) { posizione temp; temp = p ; (p->getSucc())-> setPrec(p->getPrec()); (p->getPrec()) -> setPrec(p->getSucc()); p = p -> getSucc(); delete(temp); }
Invece questo sono i metodo per inserire e visualizzare i valori :
void immissioneValori(lista & L) { posizione p; bool flag = false; char risposta ; tipoelem el = new char[20]; p = L.primoLista(); cout<<"\n"; cout<<"Inserire elemento nella lista : "; cin>>el; L.insLista(el,p); cout<<"\nVuoi inserire un altro elemento ( s/n ) ? "; fflush(stdin); cin>>risposta; if( risposta == 's' ) { flag = true; p= L.succLista(p); while(flag){ cout<<"Inserire elemento nella lista : "; fflush(stdin); cin>>el; L.insLista(el,p); cout<<"\nVuoi inserire un altro elemento ( s/n ) ? "; fflush(stdin); cin>>risposta; if( risposta == 's') { flag = true; p =L.succLista(p); } else flag = false; } } } void printLista(lista L) { posizione pos; cout << "Gli elementi della lista sono:"; pos = L.primoLista(); while(!L.fineLista(pos)) { cout << "\n["<<pos->getElemento()<<"]"; pos=L.succLista(pos); } if (L.fineLista(pos)) cout <<"\nLa lista e' terminata\n"; }
Risposte
Ciao,
dì anche che tipo di politica utilizzi (FIFO, ecc.. , se c'è) e che strutturazione hai dato (singly, doubly, con sentinella, ecc...) così è più veloce aiutarti e capire dove sta l'errore
dì anche che tipo di politica utilizzi (FIFO, ecc.. , se c'è) e che strutturazione hai dato (singly, doubly, con sentinella, ecc...) così è più veloce aiutarti e capire dove sta l'errore

è una rappresentazione circolare collegata mediante puntatori . Ogni nodo della lista è chiamato " cella " ..all'interno di ogni nodo c'è un tipoelem ( è una stringa ) e due puntatori a cella , un puntatore che punta alla cella precedente e uno alla cella successiva
Potresti mostrarci anche il main? Vedo che passi direttamente un puntatore alla lista. Sarebbe quindi utile vedere come questo puntatore varia nel tempo. Il problema potrebbe essere che tutti i nodi puntano ad una stessa locazione di memoria che viene cambiata e che conterrà alla fine solo l'ultimo valore inserito.
il main è molto semplice..
a proposito ..ho dimenticato che il prototipo di printLista è : printLista(lista & ) ..e non printLista(lista)...Vabbe comunque non funge
a proposito ..ho dimenticato che il prototipo di printLista è : printLista(lista & ) ..e non printLista(lista)...Vabbe comunque non funge
#include "lista.h" #include "cella.h" #include "FunzioniServizio.h" #include<iostream> using namespace std; int main() { lista M ; immissioneValori(M); printLista(M); }
Scusa, non avevo visto che il codice in cui creavi la lista l'avevi già postato. Ma la causa era esattamente quella che immaginavo. Quando leggi una stringa da standard input la vai a scrivere sempre nella stessa locazione di memoria che poi vai a passare al costruttore degli elementi della lista. Questo costruttore semplicemente copia il puntatore. Ma siccome tutti gli elementi puntano alla stessa locazione di memoria, conterranno anche sempre la stessa stringa (l'ultima inserita nella lista). La soluzione è quella di creare una copia delle stringhe passate al costruttore. Puoi usare strdup (che però richiede che le stringhe vengano poi deallocate con free) oppure fare la copia manualmente allocando una nuova stringa e copiandone il contenuto.
E praticamente quale funzione devo modificare...l'insLista? ...Non ho capito molto bene come fare ad apportare questa modifica..

Devi modificare l'inserimento nella lista e il distruttore (in modo che deallochi correttamente la copia della stringa).
Ok perfetto..ho risolto..ti ringrazio..=) ...ora avrei bisogno di un aiuto per quanto riguarda l'ordinamento..ecco ho implementato questo algoritmo...non so cosa ci sia di sbagliato ..ma non funge
void ordina(lista & L) { //ordina i nodi di una lista in modo crescente (insert sort) posizione min = L.primoLista(); posizione p2 = L.primoLista(); posizione p= L.primoLista(); tipoelem temp = new char[20]; for(p = L.primoLista(); p != NULL ; p = L.succLista(p)) { for(p2=p, min=p2; p2 != NULL; p2=L.succLista(p2)) { if( strcmp( L.leggiLista(p2),L.leggiLista(min)) < 0 ) { min = p2; cout<<"ciao"; strcpy(temp, L.leggiLista(p)); //Cambia ordine delle 2 parole strcpy(L.leggiLista(p),L.leggiLista(min)); strcpy(L.leggiLista(min), temp); } } } }
Al contrario del caso della creazione di nuovi elementi della lista in cui è necessario fare delle copie delle stringhe. In questo caso puoi semplicemente scambiare i puntatori e ottenere il risultato corretto. Un primo errore che trovo comunque nel tuo codice è che entrambi i cicli vanno verso la fine dell'array, mentre il ciclo interno dell'insertion sort dovrebbe visitare elementi precedenti a quello considerato in quello esterno.
potresti darmi una mano ad impostare i puntatori per favore?
In che senso? Cosa non capisci della gestione dei puntatori in questo caso?
Cioè come faccio a scambiarli ?
Esattamente come scambieresti qualsiasi altro tipo (scambio p e q che sono puntatori ad un tipo T):
Spero sia chiaro. Da questo punto di vista i puntatori non hanno niente di diverso. Un discorso diverso si ha ovviamente se si vogliono scambiare i valori nella locazione di memoria al quale puntano i puntatori invece che i puntatori stessi. Ma in questo caso non conviene.
T t = p; p = q; q = t;
Spero sia chiaro. Da questo punto di vista i puntatori non hanno niente di diverso. Un discorso diverso si ha ovviamente se si vogliono scambiare i valori nella locazione di memoria al quale puntano i puntatori invece che i puntatori stessi. Ma in questo caso non conviene.
Ho capito , ma nel mio caso ogni nodo della lista possiede un puntatore al nodo successivo e un puntatore al precedente ...Come faccio a scambiarli ?
Io mi riferivo ai puntatori ai valori, non a quelli all'elemento precedente e successivo. La struttura della lista rimane infatti invariata e puoi anche solo semplicemente scambiare tra di loro i valori contenuti nella lista come faresti per gli array. Ma il metodo corretto nel caso volessi scambiare i nodi tra di loro è in effetti semplicemente quello di scambiare i puntatori come ti ho mostrato nel post precedente, il link successivo di uno con quello dell'altro e quello precedente di uno con quello dell'altro.
Ecco la modifica dello scambio del puntatori...tuttavia il programma crasha ...Devo apportare qualche modifica nei cicli for?
posizione min = L.primoLista(); posizione p2 = L.primoLista(); posizione p= L.primoLista(); posizione temp; for(p = L.primoLista(); p != NULL ; p = L.succLista(p)) { for(p2=p, min=p2; p2 != NULL; p2=L.succLista(p2)) { if( strcmp( L.leggiLista(p2),L.leggiLista(min)) < 0 ) { min = p2; temp = L.succLista(p2); p2->setSucc(min->getSucc()); min->setSucc(temp); } } } }
Devi sostituire sia i puntatori agli elementi precedenti che a quelli successivi. Nel tuo programma hai scambiato solo quelli all'elemento successivo. È comunque secondo più semplice lavorare direttamente sui puntatori in questo caso (se hai accesso ai puntatori ovviamente - non ricordo bene la struttura del tuo programma) e usare std::swap per semplificare il codice per fare gli scambi. Ancora più semplice è scambiare i puntatori ai valori invece che quelli della lista.
Ho fatto così ..ma continua a crashare...
posizione min = L.primoLista(); posizione p2 = L.primoLista(); posizione p= L.primoLista(); for(p = L.primoLista(); p != NULL ; p = L.succLista(p)) { for(p2=p, min=p2; p2 != NULL; p2=L.succLista(p2)) { if( strcmp( L.leggiLista(p2),L.leggiLista(min)) < 0 ) { posizione temp1 = p2->getSucc(); posizione temp2 = min->getSucc(); posizione temp3 = p2->getPrec(); posizione temp4 = min->getPrec(); swap(temp1,temp2); swap(temp3,temp4); } } } }
Ma così hai scambiato solo il valore di due variabili temporanee! Mi chiedo però perché sia crashato (in teoria la tua modifica non dovrebbe avere alcun effetto). Il codice corretto, volendo usare le funzioni per accedere ai puntatori invece di accedere direttamente ai puntatori, dovrebbe essere qualcosa come il seguente:
posizione temp = min->getSucc(); min->setSucc(p2->getSucc()); p2->setSucc(temp); temp = min->getPrec(); min->setPrec(p2->getPrec()); p2->setPrec(temp); min = p2;
neanche così funge...non so più che fare