PDA

Visualizza la versione completa : [C] Raddoppio dei caratteri mediante liste


_d4vid3_
24-02-2011, 10:31
Buongiorno,
ho fatto un programma che raddoppia il numero delle 'a' presenti nella stringa di 10 caratteri immessa dall'utente. In particolare ho usato le liste.
Cio' che non capisco è perchè in questa funzione:



void elabora(tp *lista)
{elem *cursore,*supporto;
if(*lista!=NULL)
{if((*(*lista)).c=='a')
{cursore=malloc(sizeof(elem));
cursore->c='a';
cursore->prox=*lista;
*lista=cursore;
cursore=NULL;
supporto=(*(*lista)).prox;
elabora(&(supporto->prox));}
else elabora(&((*(*lista)).prox));}}


se non utilizzo il puntatore supporto e scrivo:



void elabora(tp *lista)
{elem *cursore;
if(*lista!=NULL)
{if((*(*lista)).c=='a')
{cursore=malloc(sizeof(elem));
cursore->c='a';
cursore->prox=*lista;
*lista=cursore;
cursore=NULL;
elabora(&((*(*lista))->prox));}
else elabora(&((*(*lista)).prox));}}


il compilatore mi dice che , nella riga sopra evidenziata , l'argomento di elabora è sbagliato...
a me pero' le due soluzioni sembrano identiche, nel senso che se viene trovata la 'a' riparte la esecuzione della funzione prendendo come parametro attuale :

&((*(*lista))->prox)

A cosa è dovuto?

PS La lista è cosi strutturata:


struct elemento{char c;
struct elemento *prox;};
typedef struct elemento elem;
typedef elem *tp;
tp lista1;

jobv
24-02-2011, 10:51
Ciao,

forse è uguale ma hai provato con:

&(*((*lista)->prox))

_d4vid3_
24-02-2011, 11:00
niente neanche così... in questo modo viene eseguito il programma ma appena digito la stringa l'esecuzione viene terminata 'in modo coatto' :dhò:

jobv
24-02-2011, 11:29
puoi postare tutto il codice?

_d4vid3_
24-02-2011, 13:11
Ciao! Ecco il codice completo:


#include <stdio.h>

struct elemento{char c;
struct elemento *prox;};
typedef struct elemento elem;
typedef elem *tp;
tp lista1;
void inizializzazione(tp *lista1);
void accoda(tp *lista,char el);
void elabora(tp *lista);
void stampa(tp *lista);

int main()
{printf("IL PROGRAMMA RADDOPPIA IL NUMERO DI 'A' PRESENTI NELLA STRINGA DI 10\nCARATTERI IMMESSA DALL'UTENTE\n");
char string[12];
char el;
int i;
inizializzazione(&lista1);
printf("Inserire stringa di 10 caratteri: ");
fgets(string,12,stdin);
for(i=0;i<10;i++)
{el=string[i];
accoda(&lista1,el);}
elabora(&lista1);
printf("Risultato:\n");
stampa(&lista1);
printf("\n\n");
system("PAUSE");}

void inizializzazione(tp *lista)
{*lista=NULL;}

void accoda(tp *lista,char el)
{elem *cursore;
if(*lista==NULL)
{cursore=malloc(sizeof(elem));
cursore->c=el;
cursore->prox=NULL;
*lista=cursore;}
else accoda(&((*(*lista)).prox),el);}

void elabora(tp *lista)
{elem *cursore,*supporto;
if(*lista!=NULL)
{if((*(*lista)).c=='a')
{cursore=malloc(sizeof(elem));
cursore->c='a';
cursore->prox=*lista;
*lista=cursore;
cursore=NULL;
supporto=(*(*lista)).prox;
elabora(&(supporto->prox));}
else elabora(&((*(*lista)).prox));}}

void stampa(tp *lista)
{if(*lista!=NULL)
{printf("%c",(*(*lista)).c);
stampa(&((*(*lista)).prox));}}


questa qui è la versione con il puntatore supporto, che fa funzionare il programma :)

lolide
24-02-2011, 14:25
Prova questo


elabora((*lista)->prox);


Non ho capito perchè nelle funzioni passi un puntatore a tp che è gia puntatore.
E' una cosa inutile (usato in questo contesto).

Il programma funziona si, ma è fatto mooolto male (non ti piace indentare il codice ?).

_d4vid3_
24-02-2011, 14:35
Ciao lolide,
purtroppo la soluzione che mi hai proposto la avevo gia' provata...e anche in questo caso mi lascia inserire la stringa, e quando premo invio appare il messaggio di errore e il programma viene terminato....

per quanto riguarda il passaggio parametri lo faccio per indirizzo perchè sul mio libro nel capitolo sulle liste fa degli esempi di funzioni per operare con le liste, e effettua i passaggi in questo modo... e cosi ho imparato (piu' o meno :) ) in questo modo.



Il programma funziona si, ma è fatto mooolto male (non ti piace indentare il codice ?).


Lo immagino che sia fatto male visto che sono i primissimi programmi che faccio sulle liste....e poi ho un po' una mente contorta di mio :D ...cmq non so a me davvero non funziona a meno che, come ho detto, io non metta il puntatore supporto.Per la indentatura la prossima volta provvedero'.

jobv
25-02-2011, 10:17
Ciao,

allora, come premessa direi questo:

In C il passaggio dei parametri alle funzioni è sempre per valore: di ciò che passo viene creata una copia memorizzata in una nuova variabile (quella che poi usiamo nella funzione).

Se però passiamo l'indirizzo di una variabile e indichiamo come nuova variabile una variabile puntatore cosa succede? L'indirizzo della variabile è copiato nella variabile puntatore. Risultato: possiamo modificare il valore della variabile perché al puntatore che utilizziamo nella funzione è stato assegnato un valore pari all'indirizzo della variabile che abbiamo passato come argomento.

Per esempio, nel main abbiamo:


int numero=2;
funzione(&numero);

invece, come funzione:


funzione(int *x)
{
(*x)++;
}

Al momento della chiamata il programma prende l'indirizzo di "numero" (supponiamo 1024, numero a caso) e lo copia sullo stack. La variabile x (che è un puntatore) assumerà quindi valore 1024 e, visto che il valore di una variabile puntatore è un'indirizzo di memoria: x punterà a numero e quindi possiamo variare il contenuto di numero utilizzando x.

Supponiamo ora di avere nel main una variabile puntatore e di voler creare una funzione che allochi memoria e faccia in modo che il puntatore del main punti a questa nuova locazione. Una cosa del tipo:


int *numero=NULL;
funzione(numero);

invece, come funzione:


funzione(int *x)
{
int *tmp;
tmp=(int*)malloc(sizeof(int));
x=tmp;
}

non funziona, in quanto: Il programma prende il valore numerico di NULL (indichiamolo sempre con NULL) e lo copia sullo stack. La variabile x conterrà questo valore.
Quando assegnamo ad x il valore di tmp otteniamo si che x punta alla stessa memoria a cui punta tmp ma non abbiamo cambiato il valore (e quindi l'indirizzo a cui punta) di numero!

La soluzione? Passare un puntatore ad un puntatore:


int *numero=NULL;
funzione(&numero);

invece, come funzione:


funzione(int **x)
{
int *tmp;
tmp=(int*)malloc(sizeof(int));
*x=tmp;
}

Vediamo cosa succede: il programma prende l'indirizzo di numero (che non è NULL, ma un numero in quanto NULL è il contenuto di numero, non il suo indirizzo che supponiamo essere, a caso, 1024) e lo copia sullo stack. La variabile x prende come valore 1024. Essendo un puntatore 1024 sarà visto come indirizzo di qualcosa e, essendo un puntatore ad un puntatore ad un intero, sarà visto come l'indirizzo di un puntatore ad un intero.
Veniamo a "*x=tmp" vuol dire: il valore puntato da x (quindi il valore contenuto nella locazione 1024 che è il nostro puntatore nel main) dev'essere uguale all'indirizzo puntato da tmp e quindi abbiamo cambiato il valore a cui punta numero!

Spero solo di essere stato abbastanza chiaro...anche se non ne sono sicuro!

Ad ogni modo:



struct elemento
{
char c;
struct elemento *prox;

};
typedef struct elemento elem;
typedef elem *tp;
tp lista1;
void inizializzazione(tp *lista1);
void accoda(tp *lista,char el);
void elabora(tp *lista);
void stampa(tp lista);

int main()
{
printf("IL PROGRAMMA RADDOPPIA IL NUMERO DI 'A' PRESENTI NELLA STRINGA DI 10\nCARATTERI IMMESSA DALL'UTENTE\n");
char string[12];
char el;
int i;
inizializzazione(&lista1);
printf("Inserire stringa di 10 caratteri: ");
fgets(string,12,stdin);

for(i=0;i<10;i++)
{
el=string[i];
accoda(&lista1,el);
}
elabora(&lista1);
printf("Risultato:\n");
stampa(lista1);
printf("\n\n");
system("PAUSE");}
}

void inizializzazione(tp *lista)
{
*lista=NULL;

}

void accoda(tp *lista, char el)
{
elem *cursore;

if(*lista==NULL)
{
cursore=malloc(sizeof(elem));
cursore->c=el;
cursore->prox=NULL;
*lista=cursore;
}
else
accoda(&(*lista)->prox,el);
}

void elabora(tp *lista)
{
elem *cursore;

if(*lista!=NULL)
{
if((*lista)->c=='a')
{
cursore=malloc(sizeof(elem));
cursore->c='a';
cursore->prox=*lista;
*lista=cursore;
//cursore=NULL;
elabora(&(((*lista)->prox)->prox));
}
else
elabora(&((*lista)->prox));
}

}

void stampa(tp lista)
{
if(lista!=NULL)
{
printf("%c",lista->c);
stampa(lista->prox);
}

}

Loading