PDA

View Full Version : [C]Ultimi dubbi su funzioni e puntatori


Composition86
01-09-2008, 12:36
Credo di avere gli ultimi dubbi sull'argomento programmazione in C (per ciò che mi serve), mettere insieme tutto ciò che ho imparato in questi giorni.
Dopo essere riuscito a realizzare lo stesso programma sotto riportato senza l'uso dei puntatori (quindi solo con la chiamata per valore), adesso vorrei appunto realizzarlo con un più efficiente chiamata per riferimento, ma le cose sono un po' più complicate.
Ecco una versione incompleta del programma, che immagazzina soltanto i dati richiesti (per renderlo più leggibile ho eliminato la parte che li visualizza, in cui avevo gli stessi dubbi):

#include <stdio.h>

struct persona {
char nome[25];
char cognome[25];
int eta;
};
typedef struct persona Persona;

void richiediDati (Persona *);

Persona dati[5], *wDati;
int numero;

main()
{
char fine;

printf ("Inserire il numero di dipendenti: ");
scanf ("%d", &numero);
richiediDati(dati);

printf ("Digitare una lettera e premere invio per terminare. ");
scanf ("%s", &fine);
return 0;
}

void richiediDati (Persona *wDati)
{
int i;

wDati = &dati[0];

printf ("Verranno ora richiesti i dati anagrafici relativi a %d dipendenti:\n\n", numero);

for (i = 0; i <= (numero - 1); i++) {
printf ("Inserire nome: ");
scanf ("%s", wDati[i]->nome);
printf ("Inserire cognome: ");
scanf ("%s", wDati[i]->cognome);
printf ("Inserire eta': ");
scanf ("%d", &wDati[i]->eta);
printf ("********************\n\n");
}
}


Il programma mi da' il seguente errore:

" base operand of `->' has non-pointer type `persona' "

Ecco i miei dubbi:
-Le funzioni dipendono da un puntatore a vettore "wDati": all'interno della funzione, ho passato l'indirizzo della variabile di struttura "dati" (che poi è un vettore di strutture) al puntatore. Dove sbaglio?
-So che un vettore è un puntatore che punta al suo primo elemento, per questo motivo ho eliminato [i] da ciascun ciclo for ed il programma funziona, ma ovviamente prende solo il primo dato. Perchè?
-Il programma funziona anche se sostituisco "->" con il ".", cosa che non mi aspettavo.

Noixe
01-09-2008, 14:35
Nel ciclo for c'e' [i].

Inoltre quando scrivi

wDati[i]

hai gia dereferenziato il puntatore wDati quindi deviusare il punto e non l'operatore freccia per accedere al membro della struct.

Comunque wDati lo scorri per ogni dipendente senza aver allocato prima memoria, potresti riscontrare dei problemi, accedendo a locazioni di memoria gia utilizzate.

Composition86
01-09-2008, 14:48
hai gia dereferenziato il puntatore wDati quindi deviusare il punto e non l'operatore freccia per accedere al membro della struct.
Ho capito. Ma quel mettere l'indice i nel ciclo for è ovviamente necessario a farlo funzionare, non esiste un modo per non deferenziare il puntatore e poter quindi utilizzare "->" al posto di "."? Oppure semplicemente non è possibile? Perchè usando il "." non sono più sicuro che si tratti di una chiamata per riferimento.

Comunque wDati lo scorri per ogni dipendente senza aver allocato prima memoria, potresti riscontrare dei problemi, accedendo a locazioni di memoria gia utilizzate

Qui non mi è molto chiaro, cosa devo fare per ovviare?

Noixe
01-09-2008, 15:10
Cosa centra la chiamata per riferimento?

Quella si fa relativamente al passaggio di parametri per le funzioni.

Il punto e la freccia si usano rispettivamente se hai un oggetto o un puntatore all'oggetto.

Per quanto riguarda l'array, non creare un puntatore a Persona, ma piuttosto dichiara questo:

Persona wDati[20];

In questo caso pero' puoi inserire al massimo i dati di 20 dipendenti, ma almeno le locazioni di memoria sono sicure.

Composition86
01-09-2008, 16:58
Voglio fare in modo di passare le funzioni per riferimento, e non per valore, quindi devo utilizzare i puntatori in qualche modo, cosa che sto cercando di capire.
Per questo motivo volevo utilizzare la freccia, in quanto la mia intenzione era di sfruttare i puntatori.

Quel puntatore *wDati che ho dichiarato di tipo persona, se non mi sto sbagliando, è del tutto inutile, in quanto non utilizzato nel main: il puntatore *wDati l'ho infatti definito nella funzione.

Correggimi se sbaglio.

Ti ringrazio per l'aiuto.

khelidan1980
01-09-2008, 17:21
il passaggio per riferimento già lo fai qui:


void richiediDati (Persona *wDati)


e cmq imho ha un design pessimo questa applicazione,l'array che passi a richiesta dati sarà sempre vuoto,indi per cui quel parametro non è necessario,sicuramente c'è un modo migliore di scrivere l'applicazione

Composition86
01-09-2008, 17:26
Ok. Ma poi vorrei capire questa cosa: effettivamente poi lavoro con i puntatori nella funzione?
Il dubbio mi viene dal fatto che l'uso del "." è tipico dei dati, quindi la mia impressione è che di fatto introduco i puntatori, ma poi non lavoro con gli indirizzi e quindi non capisco se il programma risulta essere realmente più efficiente.

khelidan1980
01-09-2008, 17:32
Ok. Ma poi vorrei capire questa cosa: effettivamente poi lavoro con i puntatori nella funzione?
Il dubbio mi viene dal fatto che l'uso del "." è tipico dei dati, quindi la mia impressione è che di fatto introduco i puntatori, ma poi non lavoro con gli indirizzi e quindi non capisco se il programma risulta essere realmente più efficiente.

ma non centra niente poi cosa fai all'interno,li avviene il passaggio per riferimento perchè passi un puntatore ad una struttura,infatti non viene creata una copia della struttura ma bensì lavori su quella originale,che tu dopo utilizzi il punto oppure la freccia non centra con il passaggio per riferimento,userai punto o freccia a seconda se avrai bisogno di un puntatore al campo della struttura oppure no

Composition86
01-09-2008, 17:42
Ok, allora su questo il problema non c'è, grazie. :)

DanieleC88
01-09-2008, 19:59
void richiediDati (Persona *wDati)
{
int i;

wDati = &dati[0];
Blasfemia! E che ricevi a fare il puntatore? :D

Quando tu passi un puntatore ad una funzione, la stai informando del fatto che nella zona di memoria che ha inizio da dove indicato dal puntatore c'è uno o più elementi di uno stesso tipo. In questo modo, le dai la possibilità di modificare direttamente ciò che è contenuto in quella memoria, senza aggirare l'accesso con delle copie. Perciò, se tu le passi il puntatore non devi reimpostarlo appena la funzione inizia, altrimenti ti perdi l'unica informazione interessante per quel codice.

Ora, tu stai dicendo a quella funzione che nella locazione di memoria puntata da wDati c'è almeno una struct persona che puoi leggere o scrivere. Quando accedi ad uno degli elementi con la notazione wDati[i] stai già dereferenziando il puntatore in corrispondenza dell'i-esimo elemento di tipo struct persona a partire da quella locazione: dovrai quindi trattare non un puntatore, ma una semplice struttura dati (ai quali campi devi accedere con un punto, non con l'operatore freccia).

Composition86
02-09-2008, 13:05
Blasfemia! E che ricevi a fare il puntatore? :D

Quando tu passi un puntatore ad una funzione, la stai informando del fatto che nella zona di memoria che ha inizio da dove indicato dal puntatore c'è uno o più elementi di uno stesso tipo. In questo modo, le dai la possibilità di modificare direttamente ciò che è contenuto in quella memoria, senza aggirare l'accesso con delle copie. Perciò, se tu le passi il puntatore non devi reimpostarlo appena la funzione inizia, altrimenti ti perdi l'unica informazione interessante per quel codice.

Ora, tu stai dicendo a quella funzione che nella locazione di memoria puntata da wDati c'è almeno una struct persona che puoi leggere o scrivere. Quando accedi ad uno degli elementi con la notazione wDati[i] stai già dereferenziando il puntatore in corrispondenza dell'i-esimo elemento di tipo struct persona a partire da quella locazione: dovrai quindi trattare non un puntatore, ma una semplice struttura dati (ai quali campi devi accedere con un punto, non con l'operatore freccia).
Mi stai aiutando parecchio questi giorni, ti voglio sinceramente ringraziare per tutti i consigli che mi hai dato, precisi e veloci. :)

mjordan
02-09-2008, 15:11
Mi stai aiutando parecchio questi giorni, ti voglio sinceramente ringraziare per tutti i consigli che mi hai dato, precisi e veloci. :)

Occhio che fra un po ti posta il conto PayPal... :asd:

Composition86
02-09-2008, 19:27
Speriamo di no!:D

DanieleC88
02-09-2008, 20:28
In effetti, ora che ci penso... :ciapet: :Prrr: