PDA

View Full Version : [c++]Eliminazione elementi doppi da lista ordinata


Davidino.gbr91
19-04-2009, 13:32
salve nn riesco a capire dove sbaglio....
ho bisogno di variare questa parte di programma in modo che la funzione mi cancelli gli elementi nel caso in cui ce ne siano 2 dello stesso nome:

void eliminazione()
{
string nome;
persona *p;
persona *prec = NULL;
cout <<"inserire nome da cancellare: ";
cin >> nomec;
if ( pt == null)
{
cout <<"lista vuota!";
return;
}
for (p=pt;p!=NULL && p -> nome !=nomec)
{
prec = pi;
}
if (p==NULL)
{
cout <<"nome non trovato!";
return;
}
if (prec == NULL)
{
pt == p -> succ;
delete p;
}
else
{
prec -> succ= p -> succ;
delete p;
}
}

_Claudio
19-04-2009, 14:53
Se la lista è ordinata in base al contenuto degli elementi è sufficiente confrontare un elemento col successivo e se sono uguali chiamare una funzione che elimina un elemento e ripristina la catena dei puntatori.


struct elem {
int cont;
elem* next;
}

void elimina(elem*, elem*);

int main(void) {
elem* testa;
elem* temp;

[...] inizializzazioni varie

for(temp = testa; temp->next == NULL; temp = temp->next)
if(temp->cont == temp->next->cont) elimina(testa, temp->next);

return 1;
}

void elimina(elem* t, elem* e) {
elem* temp;

for(temp = t; temp->next == NULL; temp = temp->next)
if(temp->next == e) {
temp->next = temp->next->next;
delete temp->next;
}
}

Davidino.gbr91
19-04-2009, 14:54
si ma io vorrei modificare la funzione che ho postato nn me ne serve un'altra :)
io cerco di partire da quella

_Claudio
19-04-2009, 14:55
Leggi bene quella che ti ho postato io e incorpora quanto ci trovi di buono allora...

Davidino.gbr91
19-04-2009, 14:56
era proprio quello il problema :muro:

_Claudio
19-04-2009, 15:06
:D :D :D

Non ci trovi nulla di buono?

Purtroppo il codice da te postato ha parecchi errori di forma e concettuali, non saprei proprio come modificarlo in maniera ortodossa... Per imparare non c'è niente di meglio che guardare del buon codice, capirne i concetti e farli propri.

Una domanda, ma usi C o C++? Perchè se usi C++ è sconsigliato usare NULL per motivi di consistenza dei tipi.

Inoltre in una funzione void è meglio evitare l'uso di return vuote, è un purismo ma in grossi software complessi garantisce solidità.

es.

if(a!=0) {
...
return 1;
}
... qualcos'altro alternativo all'if
return 5;


andrebbe cambiato in:


if(a!=0) {
...
} else {
... alternativo
}

return x;

Davidino.gbr91
19-04-2009, 15:19
uso il dev c++!

_Claudio
19-04-2009, 15:22
uso il dev c++!

Ok, quello è l'ambiente ma sviluppi con C o C++?

Per un semplice programma procedurale come la gestione di liste è meglio usare C. Se usi C puoi usare NULL ma devi usare printf e scanf per l'I/O che fanno parte delle librerie C standard.
Se usi C++ devi usare 0 al posto di NULL o un valore specifico che indica il valore neutro per il tipo, e devi usare cout e cin per leggere e scrivere stream dalle periferiche I/O attraverso le librerie standard C++.

Davidino.gbr91
19-04-2009, 15:27
ah te dici il linguaggio
no no è c++!

_Claudio
19-04-2009, 15:35
Allora evita l'uso di NULL, è ovvio che al livello di questo programma non cambia niente, ma è una pratica che prima si perde meglio è.
Soprattutto quando poi si sviluppano programmi con una tipizzazione più complessa.

uno può essere tentato di fare questo errore
es.

string x;
int y;

x = NULL;
y = NULL;

if(x == y) ???



string x;
int y;

x = "";
y = 0;

if(che ci scrivo?) non mi viene nemmeno


E evito pure eventuali problemi di cast e tipizzazione dinamica.

||ElChE||88
20-04-2009, 22:50
Allora evita l'uso di NULL, è ovvio che al livello di questo programma non cambia niente, ma è una pratica che prima si perde meglio è.
Ma anche no... NULL se usato solo per i puntatori va benissimo, poi ovvio che se uno inizia a usarlo invece dello 0 è sbagliato.

_Claudio
21-04-2009, 12:33
Ma anche no... NULL se usato solo per i puntatori va benissimo, poi ovvio che se uno inizia a usarlo invece dello 0 è sbagliato.

Sbaglio o stiamo dicendo la stessa cosa?

||ElChE||88
21-04-2009, 14:06
Sbaglio o stiamo dicendo la stessa cosa?
Cosa c'è di sbagliato nell'uso di NULL nel primo post? E' usato con dei puntatori...

_Claudio
21-04-2009, 17:40
Cosa c'è di sbagliato nell'uso di NULL nel primo post? E' usato con dei puntatori...

In C va ancora bene ma in C++ il libro di Bjarne Stroustrup recita il fatto che NULL può essere usato su vari tipi (non sto parlando dei puntatori) e in fase di esecuzione (quindi in stato dinamico) se questo è passato ad una funzione e questa ne esegue il cast non sapendo il tipo di partenza possono succedere casini.

Per quanto riguarda i puntatori dedica un paragrafo apposta e un suggerimento alla fine del capitolo 5 del "C++, linguaggio, libreria standard, principi di programmazione":
"la costante zero è un int. Grazie alle conversioni standard, 0 può essere utilizzato come costante di qualsiasi tipo intero, di un tipo virgola mobile, di un tipo puntatore o di un tipo puntatore a membro. Il tipo della costante 0 viene determinato dal contesto (io aggiungerei: a differenza di NULL che è una macro del preprocessore e non ha intrinsecamente legato un tipo particolare in fase di esecuzione, mentre 0 si porta dietro il suo "contesto"). Lo zero viene rappresentato da una serie di bit nulli della misura appropriata.
Nessun oggetto viene allocato con l'indirizzo 0. Perciò 0 può essere usato anche come una costante puntatore, a indicare il fatto che il puntatore non si riferisce ad alcun oggetto (io aggiungo: ma a differenza di NULL ne viene determinato il tipo in fase di parsing, evitando errori subdoli). A causa del controllo stringente del C++ sui tipi, l'uso di zero puro può comportare meno problemi."

DanieleC88
21-04-2009, 18:45
In C va ancora bene ma in C++ il libro di Bjarne Stroustrup recita il fatto che NULL può essere usato su vari tipi (non sto parlando dei puntatori) e in fase di esecuzione (quindi in stato dinamico) se questo è passato ad una funzione e questa ne esegue il cast non sapendo il tipo di partenza possono succedere casini.

Per quanto riguarda i puntatori dedica un paragrafo apposta e un suggerimento alla fine del capitolo 5 del "C++, linguaggio, libreria standard, principi di programmazione":
"la costante zero è un int. Grazie alle conversioni standard, 0 può essere utilizzato come costante di qualsiasi tipo intero, di un tipo virgola mobile, di un tipo puntatore o di un tipo puntatore a membro. Il tipo della costante 0 viene determinato dal contesto (io aggiungerei: a differenza di NULL che è una macro del preprocessore e non ha intrinsecamente legato un tipo particolare in fase di esecuzione, mentre 0 si porta dietro il suo contesto e certi cast sono vietati). Lo zero viene rappresentato da una serie di bit nulli della misura appropriata.
Nessun oggetto viene allocato con l'indirizzo 0. Perciò 0 può essere usato anche come una costante puntatore, a indicare il fatto che il puntatore non si riferisce ad alcun oggetto (io aggiungo: ma a differenza di NULL ne viene determinato il tipo in fase di parsing, evitando errori subdoli). A causa del controllo stringente del C++ sui tipi, l'uso di zero puro può comportare meno problemi."
Non sono ancora del tutto convinto che usare uno 0 sia una tecnica migliore... NULL è un ((void*)0), quindi non capisco cosa ci sia di male nell'usarlo con la testa. È sicuramente più chiaro che inizializzare tutte le variabili a 0 e poi non sapere più se era un intero o un puntatore, a metà del codice. La leggibilità viene prima di tutto, IMHO. :)

_Claudio
21-04-2009, 19:22
Non sono ancora del tutto convinto che usare uno 0 sia una tecnica migliore... NULL è un ((void*)0), quindi non capisco cosa ci sia di male nell'usarlo con la testa. È sicuramente più chiaro che inizializzare tutte le variabili a 0 e poi non sapere più se era un intero o un puntatore, a metà del codice. La leggibilità viene prima di tutto, IMHO. :)

E cosa cambia dall'inizializzare tutto con 0 o con NULL come leggibilità?
La differenza fondamentale è che 0 non è una macro del preprocessore.
Inoltre cosa è NULL varia da macchina a macchina, normalmente equivale (coattivamente per standard) a 0 (o (void*)0)) ma non è detto.
Poi se si usa con la testa NULL allora tutto è possibile, anche la giustizia nel mondo :sofico:
Poi se lo dice chi ha inventato il C++... nel caso ancora non vogliate credermi... fare un atto di fede come tributo non sarebbe male... :fagiano:

DanieleC88
21-04-2009, 19:29
E cosa cambia dall'inizializzare tutto con 0 o con NULL come leggibilità?
Che evidenzi subito il tipo, assegnando zero ad una variabile o confrontandola non puoi dire che tipo di "numero" sarebbe (int, float, puntatore, etc).
Inoltre cosa è NULL varia da macchina a macchina
Hmm, questa me la devi spiegare, o è una macro del preprocessore o è legata ad un'architettura hardware. :)
Poi se lo dice chi ha inventato il C++... nel caso ancora non vogliate credermi... fare un atto di fede come tributo non sarebbe male... :fagiano:
Che significa, anche Aristotele aveva detto che la terra è al centro dell'universo, e per 2000 anni tutti hanno fatto di sì con la testa perché "ipse dixit". :)

_Claudio
21-04-2009, 21:32
Che evidenzi subito il tipo, assegnando zero ad una variabile o confrontandola non puoi dire che tipo di "numero" sarebbe (int, float, puntatore, etc).


E assegnandogli NULL?


Hmm, questa me la devi spiegare, o è una macro del preprocessore o è legata ad un'architettura hardware. :)


Il preprocessore fa parte del compilatore e il compilatore spesso è fatto ad hoc per l'hardware... o sbaglio? O per lo meno le librerie che definiscono l'ambiente cambiano e con esse il valore della macro #define NULL. Cioè posso sempre programmare usando gcc ma specifico che sto programmando codice per dispositivi embedded e uso librerie particolari.


Che significa, anche Aristotele aveva detto che la terra è al centro dell'universo, e per 2000 anni tutti hanno fatto di sì con la testa perché "ipse dixit". :)

Sono due cose ben diverse, del moto dei pianeti all'epoca di Aristotele nulla si sapeva, il C++ è stato creato da Bjarne quindi suppongo che lui conosca ogni singolo dettaglio meglio di chiunque altro.

DanieleC88
22-04-2009, 01:04
E assegnandogli NULL?
Espliciti che fai riferimento ad un puntatore. :)
Il preprocessore fa parte del compilatore e il compilatore spesso è fatto ad hoc per l'hardware... o sbaglio? O per lo meno le librerie che definiscono l'ambiente cambiano e con esse il valore della macro #define NULL. Cioè posso sempre programmare usando gcc ma specifico che sto programmando codice per dispositivi embedded e uso librerie particolari.
Come vuoi, ma il discorso non cambia... Ad esempio MSVC++ 8 definisce così il NULL:
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
Quindi semplicemente non vedo il problema pratico. :)
Sono due cose ben diverse, del moto dei pianeti all'epoca di Aristotele nulla si sapeva, il C++ è stato creato da Bjarne quindi suppongo che lui conosca ogni singolo dettaglio meglio di chiunque altro.
Era un esempio, non accetto che mi si venga detto di ricevere le cose per "atto di fede", neanche se fosse Bjarne in persona a dirmele. :)

ciao ;)

_Claudio
22-04-2009, 10:54
Espliciti che fai riferimento ad un puntatore. :)


A livello di scrittura del codice... ma se uno scrive codice sapientemente si ricorda che quella variabile è un puntatore.
E personalmente do maggior priorità alla correttezza del codice scritto rispetto la sua chiarezza... mi sembra sacrosanto.


Come vuoi, ma il discorso non cambia... Ad esempio MSVC++ 8 definisce così il NULL:
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
Quindi semplicemente non vedo il problema pratico. :)


msvc è un compilatore potente per sistemi mediamente potenti (normalmente pc). Come ti ho già scritto altri compilatori hanno altre implementazioni, se faccio porting dando per scontato che NULL ha quel valore...


Era un esempio, non accetto che mi si venga detto di ricevere le cose per "atto di fede", neanche se fosse Bjarne in persona a dirmele. :)

ciao ;)

L'ho detto provocatoriamente... ovvio. Ma le motivazioni sono evidenti, al di là che lo dica Bjarne o meno.

Il problema è che se uso C++ personalmente cerco di essere il più aderente possibile al linguaggio e alla sua filosofia (che comprende il non usare il più possibile le direttive del preprocessore) e cerco di scrivere programmi il più corretti possibili mettendo in secondo piano la leggibilità. Poi è un mio punto di vista... spero sia condiviso... ma se non lo è amen, spero di non trovarmi mai a lavorare in futuro con del codice leggibilissimo ma che ha errori subdoli come quello riguardante il NULL su compilatori diversi.

DanieleC88
22-04-2009, 12:16
A livello di scrittura del codice... ma se uno scrive codice sapientemente si ricorda che quella variabile è un puntatore.
Ma non è detto che chi legge il codice sia chi l'ha scritto, o magari lo rileggi dopo mesi e non ricordi più cosa intendevi fare. Per questo io intendo che "la leggibilità è tutto", chiaro che il codice deve essere corretto... :)

Ascolta, non voglio che tu fraintenda i toni che ho avuto nella discussione: non sto dicendo che hai torto, è solo che non ho compreso dove nasca il problema nell'utilizzo del NULL, e che a me sembra una pratica perfettamente lecita. Se dovessi sbagliarmi... sono sempre disposto ad imparare. ;)

ciao ;)

_Claudio
22-04-2009, 13:36
Ma non è detto che chi legge il codice sia chi l'ha scritto, o magari lo rileggi dopo mesi e non ricordi più cosa intendevi fare. Per questo io intendo che "la leggibilità è tutto", chiaro che il codice deve essere corretto... :)

Ascolta, non voglio che tu fraintenda i toni che ho avuto nella discussione: non sto dicendo che hai torto, è solo che non ho compreso dove nasca il problema nell'utilizzo del NULL, e che a me sembra una pratica perfettamente lecita. Se dovessi sbagliarmi... sono sempre disposto ad imparare. ;)

ciao ;)

Certo, comprendo i toni, niente di polemico... ci mancherebbe. :D

Il problema dell'utilizzo della NULL è esposto molto bene sul libro scritto da Bjarne, leggendolo ho trovato la spiegazione molto convincente. Poi anche l'autore del libro (e del C++) dice che comunque non è scorretto, pone la cosa al pari di usare le #define in codice C++ al posto della parola chiave const. E ogni volta che fa riferimento alla questione non perde l'occasione per deprecarla. Poi è lecito, perfettamente lecito e ci mancherebbe, però chi la usa deve avere ben chiare le motivazioni esposte nel libro e non incappare in eventuali errori, usarla igorando certi particolari in applicazioni complesse è a mio avviso una cosa poco furba. Tutto qui.

BrutPitt
22-04-2009, 15:55
Mi trovo concorde con quanto scritto da _Claudio sul fatto che il NULL, definito come "(void *) 0", sia da deprecare.
Anche se, come ha gia' fatto notare Lui, ormai in C++ il NULL e' definito come "0"... dato che in caso contrario necessiterebbe di cast... per cui c'e' anche poca possibilita' di confondersi.

Ma usare il nullptr che dovrebbe appartenere allo standard gia' dall'ANSI C++03?

int *p = nullptr;

Oltretutto leggevo (se riesco a recuperare l'articolo lo posto), che con l'introduzione dello standard ANSI C++09 (gia' definito nel 2008), sara deprecata (sebbene ancora consentita) anche una definizione del tipo:

int *p = 0;

Vediamo se nelle prossime versioni di C++ troviamo una dichiarazione del genere:

#define NULL nullptr

:D

BrutPitt
22-04-2009, 16:12
Recuperato articolo e mi correggo da solo:

http://www.maccompanion.com/macc/archives/March2007/Columns/AccordingtoHoyle.htm

nullptr era gia' in uso in molti compilatori... gia' in VC2005 o gcc4.0 ... ma effettivamente sara' standard da C++09.