|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
[C] Strutture dati : sclero. (aggiornato nuovo programma, nuovo problema)
Scusate ragazzi, questa è la mia unica spiaggia non so a cui rivolgermi. L'incubo finirà a gennaio, intanto vi dovete sorbire i miei 3d a decine, perchè purtroppo ho un prof incompetente e non so a chi chiedere. Dopo aver perso ore a capire le strutture dati, sono riuscito a fare un programma basato sulle strutture dati che "su carta", coi disegnini dei mattonici ecc, funziona, ma nel programma no.
Mi sapete dire dove sbaglio? Questo è il codice : Codice:
#include<stdio.h> #include<stdlib.h> struct lis { int inf; struct lis *pun; }; struct lis *genLista(); void stampaLista(struct lis *); struct lis *cancNum(struct lis *); int main(){ struct lis lista; struct lis *puntalista; puntalista=genLista(); stampaLista(puntalista); puntalista=cancNum(puntalista); stampaLista(puntalista); system("PAUSE"); return(0); } struct lis *genLista(){ struct lis *p,*paus; int n; p=(struct lis *)malloc(sizeof(struct lis)); printf("\nInserisci numero elementi lista : "); scanf("%d",&n); printf("\nInserisci 1o elemento : "); scanf("%d",&p->inf); paus=p; for(int i=2;i<=n;i++){ paus->pun=(struct lis *)malloc(sizeof(struct lis)); paus=paus->pun; printf("\nInserisci %do elemento: ",i); scanf("%d",&paus->inf); } paus->pun=NULL; return(p); } void stampaLista(struct lis *p){ printf("\nLA LISTA E' :\n"); while(p!=NULL){ printf("%d",p->inf); printf("-->"); p=p->pun; } printf("FINE LISTA"); printf("\n\n"); } struct lis *cancNum(struct lis *p){ struct lis *paus,*paus2; while(((p->inf)%2==0)&&(p!=NULL))p=p->pun; paus=p; while(paus!=NULL){ if(((paus->inf)%2==0)){ paus2=paus->pun; paus->pun=NULL; paus=paus2; continue; } paus=paus->pun; } return(p); } Quello che ho fatto è dividire la cancellazione se il numero è il primo della lista, o se è successivo al primo della lista. Se è il primo della lista, la cancellazione mi riesce bene. Non posso mettere tutto in uno altrimenti perdere il puntatore alla testa della lista, e perderei di conseguenza la possibilità di stampa. Comunque, il rpoblema viene quando devo trovare i successivi elementi pari da eliminare; uso 2 puntatori ausiliari, che scorrono la lista e eliminano il numero pari se c'è, se non c'è l'if non viene fatto e il primo puntatore ausiliario viene spostato di 1 mattoncino, mentre se l'if viene fatto avviene la cancellazione, ma il continue evita che il primo puntatore ausiliario si sposti di un mattoncino. Dove sbaglio?
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one Ultima modifica di The-Revenge : 16-12-2009 alle 13:12. |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2773
|
Gli errori sono sostanzialmente due:
immagina la lista come una catena: quando cancelli un nodo è come se eliminassi un anello della catena, per far sì che la catena resti insieme devi legare tra loro l'anello che precedeva l'anello eliminato e il successivo. Quello che fai qui: Codice:
struct lis *cancNum(struct lis *p){ struct lis *paus,*paus2; while(((p->inf)%2==0)&&(p!=NULL))p=p->pun; paus=p; while(paus!=NULL){ if(((paus->inf)%2==0)){ paus2=paus->pun; paus->pun=NULL; paus=paus2; continue; } paus=paus->pun; } return(p); } Il secondo errore è che non deallochi la memoria allocata. |
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
Quote:
mi potresti dire cosa ho sbagliato esattamente?
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
|
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2773
|
Il problema è che al passo generico stai confrontando un nodo ma non hai memoria del precedente e quindi non ti è possibile risanare la catena
Codice:
while(paus!=NULL){ if(((paus->inf)%2==0)){ paus2=paus->pun; paus->pun=NULL; paus=paus2; continue; } |
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
l'ho corretto e sembra funzionare. Capito dove sbagliavo : andavo di pari passo ad una cella, senza poter ritornare alla precedente, invece ora lascio idnietro paus1, porto avanti paus2 e poi creo il ponte tra paus1 e il successivo e scollego paus2.
Per la deallocazione, dealloco paus1 e 2 alla fine del while? cosi? Codice:
struct lis *cancNum(struct lis *p){ struct lis *paus,*paus2; while(((p->inf)%2==0)&&(p!=NULL))p=p->pun; paus=p; while(paus!=NULL){ paus2=paus->pun; if(((paus2->inf)%2==0)){ paus->pun=paus2->pun; paus2->pun=NULL; } paus=paus->pun; } free(paus); free(paus2); return(p); }
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
![]() |
![]() |
![]() |
#6 |
Member
Iscritto dal: May 2006
Messaggi: 86
|
Codice PHP:
![]() |
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2773
|
Quote:
|
|
![]() |
![]() |
![]() |
#8 |
Member
Iscritto dal: May 2006
Messaggi: 86
|
Codice PHP:
|
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
Quote:
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
|
![]() |
![]() |
![]() |
#10 | |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
Quote:
Comunque per il fatto del casting che mi hai fatto notare, c'è scritto sul libro di fare cosi..nn so. Comunque ho qualche problema a capire la deallocazione ![]()
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
|
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
è deallocato bene cosi? ho usato la deallocazione sia sul puntalista che sul secondo puntatore ausliario. Credo di aver capito il concetto.
Codice:
struct lis *cancNum(struct lis *p){ struct lis *paus,*paus2; while(((p->inf)%2==0)&&(p!=NULL)){paus=p; p=p->pun; p->pun=NULL; free(paus); } paus=p; while(paus!=NULL){ paus2=paus->pun; if(((paus2->inf)%2==0)){ paus->pun=paus2->pun; paus2->pun=NULL; free(paus2); } paus=paus->pun; } return(p);
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
![]() |
![]() |
![]() |
#12 |
Member
Iscritto dal: May 2006
Messaggi: 86
|
Se deallochi, cancelli dalla faccia della terra quello che passi come argomento, devi solo ricordarti che quando lo fai non hai più niente di ciò che era presente nella struttura.
per quanto riguarda l'allocazione.. Codice PHP:
E' come comprare un garagage dimensione limousine quando hai una smart... non è che non funzioni, è solo uno spreco, concettualmente cannato (oltre che economicamente ) ![]() Ah, come nota trasversale, compilando con gcc -Wall, a me il cast lo segnala pure come warning, visto che in c i cast pare non siano necessari... |
![]() |
![]() |
![]() |
#13 | |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2773
|
Quote:
La prima assegnazione a NULL è un errore, perché nella istruzione precedente hai assegnato a p il nodo successivo, quindi stai agendo su un nodo che non hai ancora esaminato. La seconda assegnazione a NULL è inutile perché tanto agisce su memoria che subito dopo deallochi con free. |
|
![]() |
![]() |
![]() |
#14 | |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
Quote:
2)si, ho fatto un errore in realtà volevo scrivere paus->pun=NULL. Questo porta allo stesso problema che hai esaminato nel 3 punto 3)qui c'è un problema che hai sollevato e che ho chiesto stamane anche io al mio prof quando spiegava, e mi ès tato risposto in un certo modo ecco xke ho scritto null anche sapendo che dopo deallocavo con free. In pratica paus2->pun punta a un area che ha 2 puntatori quindi posso scollegare paus2. Il mio prof stamattina scollegava sempre paus2->pun prima di deallocare paus2. Io gli ho chiesto se non fosse possibile deallocare direttamente paus2 senza scollegarlo, dato che comunque la parte restante della catena era collegata ad un altro puntatore, e lui mi ha detto che non era sicuro ma che pensava che deallocando direttamente si sarebbe persa anche la restante parte della catena, nonostante fosse collegata ad un altro puntatore. Ecco perchè scollego prima di deallocare, nonostante ero consapevole che avrei deallocato. Quindi mi dite che non c'è bisogno di scollegarlo? Il prof , ripeto, non era sicuro. Stessa cosa nel punto 2, corretto l'errore porterebbe a questo problema. X blackauron : guarda, sicuramente avrai ragione ma il libro e il prof dicono in quella maniera e, siccome non devo fare nulla di professionale ma solo cose didattiche, preferisco attenermi. Comunque con quel cast io stavo solo dichirando un puntatore che punta a una struttura di tipo lis, e questo puntatore punta a un area di memoria che alloco con malloc , usando sizeof per ricavare la grandezza della struttura di tipo lis. Non vedo dove è l'errore che tu dici ![]() Comunque vi ringrazio per l'aiuto e per li speigazione, mi siete stati di grande aiuto ![]() Alla fine dovrebbe essere cosi Codice:
struct lis *cancNum(struct lis *p){ struct lis *paus,*paus2; while((p!=NULL)&&((p->inf)%2==0)){paus=p; p=p->pun; paus->pun=NULL; free(paus); } paus=p; while(paus!=NULL){ paus2=paus->pun; if(((paus2->inf)%2==0)){ paus->pun=paus2->pun; paus2->pun=NULL; free(paus2); } paus=paus->pun; } return(p);
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one Ultima modifica di The-Revenge : 15-12-2009 alle 19:59. |
|
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2773
|
Riguardo l'assegnazione a NULL confermo che è inutile, la free semplicemente dealloca un blocco di memoria precedentemente allocato, se facesse quello che dice il prof dovrebbe inferire i campi della struttura puntata dal puntatore passato come parametro (cosa impossibile) e a quel punto deallocare a cascata i vari puntatori.
Non ho invece capito la questione del cast, cioè, non ho capito di cosa state parlando. |
![]() |
![]() |
![]() |
#16 | |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
Quote:
![]() Per quanto riguarda la questione del cast lui intende questo : Codice:
p=(struct lis *)malloc(sizeof(struct lis));
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
|
![]() |
![]() |
![]() |
#17 |
Member
Iscritto dal: May 2006
Messaggi: 86
|
con il cast fai in modo che in p ci stia un puntatore a struct lis, mentre allochi uno spazio di dimensione struct lis.
In parole povere, faccio un esempio ![]() 1) sizeof(struct lis) = 10 bytes 2) sizeof(sruct lis *) = 4 bytes ( ricordiamoci che struct lis* contiene solo un indirizzo di memoria, quindi lo spazio di cui necessita è esiguo) 3) malloc(sizeof(struct lis)) creo uno spazio in memoria di dimensione 10 bytes 4) ( struct lis*)malloc(sizeof(struct lis)) do ai 10 bytes la forma di un puntatore a struct lis, che richiede solo 4 bytes. I restanti 6 bytes sono memoria sprecata. PS: i valori li ho sparati a caso, giusto per far capire il concetto |
![]() |
![]() |
![]() |
#18 |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2773
|
Non funziona così: malloc alloca un'area di memoria della dimensione desiderata (quella passata come parametro) e restituisce un puntatore a quell'area di memoria. Dovendo il valore restituito essere generico viene restituito un puntatore a void. Il cast esplicito serve ad evitare un warning del compilatore (non so se ci siano anche compilatori che danno errore) che avvertirebbe del fatto che si sta assegnando un valore "void*" a una variabile di tipo diverso, in questo caso "struct lis*"
|
![]() |
![]() |
![]() |
#19 | |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
Quote:
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
|
![]() |
![]() |
![]() |
#20 |
Member
Iscritto dal: May 2006
Messaggi: 86
|
eh si, mi sa che ieri ero particolarmente in aria:leggevo *p e nella mia testa pensavo a **p ... pazienza
![]() Resta il fatto che a me il warning lo da solo se il cast lo metto... |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 20:09.