PDA

View Full Version : [c] Problema con i puntatori


ioshi
16-01-2009, 14:30
Salve a tutti del forum.

Ragazzi sto facendo un programma per l'università sulle strutture dinamiche e più precisamente sulle code.

Ho fatto diciamo il programma però non mi funziona bene.Facendo il debug con il dev-c mi sono accorto di una cosa.Dopo aver inizializzato i puntatori nel main con NULL quando li vado a passare nelle funzioni per inserire ed eliminare un elemento i puntatori cambiao valore passando da null ad due indirizzi separati.Quando la funzione termina e ritorno al main i puntatori perdono il valore acquisito e ritornano a NULL.

Sono disperato vi prego aiutatemi.

Di seguito vi posto il sorgente.

P.S. La versione di dev utilizzata e l'ultima cioè la 5.




#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#define max 50
//tipi di dati astratti utilizzati
typedef char stringa[50];
//struttura
struct utente{
int numero;
stringa nome;
struct utente *next;
};
typedef struct utente UTENTE;
typedef UTENTE *nuovoutente;

void pusha(int numero,nuovoutente *testa,nuovoutente *coda);
int poppa(int numero,nuovoutente *testa,nuovoutente *coda);


int main(){
int scelta=0,errore=0;
UTENTE ute;
nuovoutente testa;
nuovoutente coda;
testa=NULL;
coda=NULL;
do{
printf("DIGITA 1 per inserire");
printf("\n");
printf("DIGITA 2 per estrarre");
printf("\n");
printf("DIGITA 3 per uscire");
printf("\n");
scanf("%d",&scelta);
switch(scelta){
case 1:{
printf("Inserisci il numero");
printf("\n");
scanf("%i",&ute.numero);
printf("Inserisci il nome");
printf("\n");
scanf("%s",ute.nome);
printf("\n");
pusha(ute.numero,&testa,&coda);
}break;
case 2:{
errore=poppa(&ute.numero,&testa,&coda);
if(errore==1){
printf("%d",ute.numero);
printf("\n");
}
else printf("La coda e\' vuota\n");
}break;
}
}while(scelta!=3);
system("PAUSE");
return 0;
}

void pusha(int numero,nuovoutente *testa,nuovoutente *coda){
UTENTE *nuovoutente;
nuovoutente=(UTENTE*)malloc(sizeof(UTENTE));
nuovoutente->numero=numero;
nuovoutente->next=NULL;
if(testa==NULL){
*testa=nuovoutente;
*coda=nuovoutente;
}
else{
(*coda)->next=nuovoutente;
*coda=nuovoutente;
}
}


int poppa(int numero,nuovoutente *testa,nuovoutente *coda){
if(testa==NULL){
numero=(*testa)->numero;
(*testa)=(*testa)->next;
return 1;
}
else return 0;
}

Kenger
16-01-2009, 15:50
La prossima volta usa il tag [CODE] però :p

Comunque il problema è che il c passa i parametri per valore, che vuol dire che non passa la variabile ma passa solo una copia che poi verrà distrutta alla fine della chiama alla funzione.
Per risolvere devi cambiare la funzione in modo che prenda in ingresso il puntatore al puntatore e poi gestirlo di conseguenza.
Ah, chiaramente quando chiami la funzione poi dovrai passare il puntatore al puntatore, non più il puntatore direttamente.

EDIT: Scusa, dando una rapida letta al codice vedo che lo hai già fatto. Se per favore usi il tag code e re-incolli il codice lo guardo meglio. ^^

ioshi
16-01-2009, 16:30
Ecco l'ho modificato....Non riesco a venirne a capo ci sto da ieri su questo codice l'ho riscritto 3 volte da capo....ma nada....commetto sempre lo stesso errore che non riesco a capire dove sta...
Ma....l'ho fatto alle superiori usando anche quaiche cosa del c++ e l'ho sempre fatto bene....ora usando solo c sto andando in crisi....
Mi sono arruginito....

k0nt3
16-01-2009, 17:31
ovviamente stai assumendo che passando un puntatore stai passando la variabile per riferimento, ma in realtà stai passando l'indirizzo della variabile per valore.
quindi quando assegni un puntatore all'interno della funzione lo cambi solo localmente alla funzione.
la soluzione è passare un puntatore a puntatore quando serve (cioè quando vuoi cambiare riferimento al puntatore)

ioshi
16-01-2009, 17:38
se non sbaglio l'ho passato un puntatore di puntatore come argomento no?

k0nt3
16-01-2009, 17:49
gli ho dato una lettura veloce al codice, ho risposto in base al tipo di errore che hai segnalato :p
comunque magari ci dò un'occhiata più approfondita appena ho tempo

k0nt3
16-01-2009, 18:06
siccome non mi oriento molto con troppe definizioni di tipi.. ho provato così e ora funziona :sofico: :

#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#define max 50

//struttura
typedef struct struct_utente {
int numero;
char nome[50];
struct struct_utente *next;
} utente;

void pusha(int numero, utente **testa, utente **coda);
int poppa(int numero, utente **testa, utente **coda);


int main(){
int scelta=0,errore=0;
utente ute;
utente *testa;
utente *coda;
testa=NULL;
coda=NULL;
do{
printf("DIGITA 1 per inserire");
printf("\n");
printf("DIGITA 2 per estrarre");
printf("\n");
printf("DIGITA 3 per uscire");
printf("\n");
scanf("%d",&scelta);
switch(scelta){
case 1:{
printf("Inserisci il numero");
printf("\n");
scanf("%i",&ute.numero);
printf("Inserisci il nome");
printf("\n");
scanf("%s",ute.nome);
printf("\n");
pusha(ute.numero,&testa,&coda);
}break;
case 2:{
errore=poppa(ute.numero,&testa,&coda);
if(errore==1){
printf("%d",ute.numero);
printf("\n");
}
else printf("La coda e\' vuota\n");
}break;
}
}while(scelta!=3);
getchar();
return 0;
}

void pusha(int numero, utente **testa, utente **coda){
utente *new;
new=(utente*)malloc(sizeof(utente));
new->numero=numero;
new->next=NULL;
if(*testa==NULL){
*testa=*coda=new;
printf("inserito %d\n",(*testa)->numero);
}
else{
*coda=new;
}
}


int poppa(int numero, utente **testa, utente **coda){
if(*testa==NULL){
return 0;
}
else {
numero=(*testa)->numero;
(*testa)=(*testa)->next;
return 1;
}
}


avevi anche invertito l'if in poppa

ioshi
16-01-2009, 18:37
bhe non so perchè ma non mi va...quando lo compilo mi da molti errori....
poi non posso usare new(perchè se non erro è una funzione di c++ ed il prof vuole puramente c)
comunque puoi spiegarmi dove ho sbagliato?e se nel caso farmi un esempio?

k0nt3
16-01-2009, 18:46
bhe non so perchè ma non mi va...quando lo compilo mi da molti errori....
poi non posso usare new(perchè se non erro è una funzione di c++ ed il prof vuole puramente c)
comunque puoi spiegarmi dove ho sbagliato?e se nel caso farmi un esempio?
new l'ho usato come nome per la variabile, essendo codice C non è una keyword.
sinceramente non lo so esattamente dove hai sbagliato :fagiano: perchè quando ci sono troppe definizioni faccio confusione
sicuramente l'if in poppa era invertito
mi sembra strano che ti da errori perchè devcpp dovrebbe usare lo stesso compilatore che uso io (cioè gcc). puoi postare gli errori che ti da?
tra l'altro ti consiglierei di usare codeblocks che è molto meglio di dev-cpp

ps. forse ho capito... dev-cpp è un compilatore c++ quindi ti da errore sulla new! prova a cambiargli nome (ad esempio nuovo)

k0nt3
16-01-2009, 18:57
ok ho confrontato il codice..
avevi sbagliato nell'if in pusha quando controllavi se testa era NULL

if(testa==NULL){

il codice giusto era:

if(*testa==NULL){


lo stesso errore c'è in poppa

ioshi
16-01-2009, 19:05
ok grazie mille :D :D :D
Comunque anche io non uso molto le definizioni ma il prof le vuole per la solita cosa del software più leggibile e vuole che usiamo come compilatore il dev 5...
Anche se io preferisco la versione precedente che ha un debugger comodissimo rispetto all'attuale versione(che odio anche perchè errori che non mi da nella 4 me li da nella 5).
Io come compilatore editor ho sempre usato il turbo c(la versione che va in finestra dos) la adoro.
Ora provo e mi riscrivo tutto il codice da capo cercando di risolvere il tutto e poi riposterò la nuova versione di codice pulita.Grazie ancora!

ioshi
16-01-2009, 19:10
Dopo un controllo del codice ed un debbugata ho trovato ma non risolto il problema prima esposto,cioè quando vado ad estrarre un elemento mi estra sempre l'ultimo fino a darmi coda vuota.
La funzione svolge correttamente il suo lavoro ma nel momento in cui ritorna al main nella variabile ute.numero rimane sempre l'ultimo valore salvato(nonostante lo passi per indirizzo) e quindi stampa sempre lo stesso...
Perchè????