Funzione in C - stampa testo
Buongiorno a tutti,
nell'eseguire questo programmino mi ritorna errore: "invalid operands to binary +"
Ho definito una funzione che mi ritorni un dato strutturato contenente un array:
La funzione è del tipo ris:
Ora il problema sussiste nella stampa del campo testo, ad esempio se far eseguire questa funzione:
mi da errore!
dove sbaglio?
grazie
nell'eseguire questo programmino mi ritorna errore: "invalid operands to binary +"
Ho definito una funzione che mi ritorni un dato strutturato contenente un array:
typedef struct{ int giorno; int mese; }tdata; typedef struct{ int ore; int minuti; }torario; typedef struct{ tdata data; torario orario; int numero; char testo[200]; }tmessaggi; tmessaggi messaggio[N]; typedef struct{ tmessaggi messaggio[N]; int num; }ris;
La funzione è del tipo ris:
ris ElencoMessaggi(tmessaggi a[],int numerotel){ ris r; int i; r.num=0; for(i=0;i<dim;i++){ if(numerotel==a[i].numero){ r.messaggio[r.num]=a[i]; r.num++; } } return r; }
Ora il problema sussiste nella stampa del campo testo, ad esempio se far eseguire questa funzione:
printf("%s",ElencoMessaggi(messaggio,12345).messaggio[0].testo);
mi da errore!
dove sbaglio?
grazie
Risposte
"ELWOOD":
nell'eseguire questo programmino mi ritorna errore: "invalid operands to binary +"
Probabilmente stai sommando due variabili per cui non è definita la somma (due struct per esempio). Ma nel codice che hai postato non vedo simboli +, l'errore è da un'altra parte.
Questo sarebbe il codice completo:
L'ERRORE sta nella stampa di ElencoMessaggi(messaggio,n).messaggio.testo
mentre gli altri campi di ElencoMessaggi(messaggio,n) me li stampa tranquillamente, ma non capisco perchè mi da errore solo per la stringa testo
#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 50 int main(int argc, char *argv[]) { typedef struct{ int giorno; int mese; }tdata; typedef struct{ int ore; int minuti; }torario; typedef struct{ tdata data; torario orario; int numero; char testo[200]; }tmessaggi; tmessaggi messaggio[N]; //messaggi messaggio; //Definisco una struttura dati opportuna per la funzione ElencoMessaggi (visto che non può restituire un array ma può restituire una struct) typedef struct{ tmessaggi messaggio[N]; int num; }ris; //Funzione random numeri int random(int min,int max){ int ran; ran=rand()%(max+min-1)+min; return ran; } int i=0,dim; char termina='n'; while(i<N && termina=='n'){ printf("\t *** Ciao, inserisci i dati messaggio nr. %d ***",i+1); messaggio[i].data.giorno=random(1,31); messaggio[i].data.mese=random(1,12); printf("\n\n ore:"); scanf("%d",&messaggio[i].orario.ore); while(messaggio[i].orario.ore<0 || messaggio[i].orario.ore>23){ printf("\nIl valore delle ore deve essere compreso tra 0 e 23.\nInserisci un nuovo valore per le ore:"); scanf("%d",&messaggio[i].orario.ore); } printf("\n\n minuti:"); scanf("%d",&messaggio[i].orario.minuti); while(messaggio[i].orario.minuti<0 || messaggio[i].orario.minuti>59){ printf("\nIl valore dei minuti deve essere compreso tra 0 e 59.\nInserisci un nuovo valore per i minuti:"); scanf("%d",&messaggio[i].orario.minuti); } printf("\nNumero di telefono:"); scanf("%d",&messaggio[i].numero); printf("\nTesto del messaggio:"); fflush(stdin);gets(messaggio[i].testo); printf("\n Terminare l'inserimento?s/n:"); scanf("%c",&termina); i++; dim=i; } //STampo i campi messaggio: printf("\t *** Elenco messaggi: ***\n\n"); for(i=0;i<dim;i++){ printf(" %d \t %d \t %d \t %d \t %d \t %s \n\n",messaggio[i].data.giorno,messaggio[i].data.mese,messaggio[i].orario.ore,messaggio[i].orario.minuti,messaggio[i].numero,messaggio[i].testo); } // Funzione percentuale orario: int PercentualeOrario(tmessaggi a[],int ore, int min){ float percentuale,somma=0; for(i=0;i<dim;i++){ if(a[i].orario.ore>ore){ somma+=1; } else{ if(a[i].orario.ore==ore && a[i].orario.minuti>min){ somma+=1; }else{somma+=0;} } } percentuale=(somma/dim)*100; return percentuale; } int o,m; printf("\n\n%d\n\n",PercentualeOrario(messaggio,13,30)); printf("\n Inserire l'orario dopo il quale si vuole conoscere la percentuale di sms ricevuti:\nore:"); scanf("%d",&o); printf("\n minuti:"); scanf("%d",&m); printf("La percentuale di sms mandati dopo tale ora e: %d per cento\n\n",PercentualeOrario(messaggio,o,m)); /* typedef struct{ tdata data; torario orario; int numero; char testo[200]; }tmessaggi; tmessaggi messaggio[N]; messaggi messaggio; */ //FUnzione elenco ris ElencoMessaggi(tmessaggi a[],int numerotel){ ris r; int i; r.num=0; for(i=0;i<dim;i++){ if(numerotel==a[i].numero){ r.messaggio[r.num]=a[i]; //r.messaggio[r.num].testo=a[i].testo; //r[i].data.giorno=a[i].data.giorno; //r[i].data.mese=a[i].data.mese; //r[i].orario.ore=a[i].orario.ore; //r[i].orario.minuti=a[i].orario.minuti; //r[i].testo=a[i].testo; r.num++; } } return r; } int n; printf("Inserire il numero di telefono:"); scanf("%d",&n); printf("I messaggi mandati da tale numero sono:\n\n"); for(i=0;i<dim;i++){ printf(" %d \t %d \t %d \t %d \t %s \n\n",ElencoMessaggi(messaggio,n).messaggio[i].data.giorno,ElencoMessaggi(messaggio,n).messaggio[i].data.mese,ElencoMessaggi(messaggio,n).messaggio[i].orario.ore,ElencoMessaggi(messaggio,n).messaggio[i].orario.minuti,ElencoMessaggi(messaggio,n).messaggio[i].testo); } system("PAUSE"); return 0; }
L'ERRORE sta nella stampa di ElencoMessaggi(messaggio,n).messaggio.testo
mentre gli altri campi di ElencoMessaggi(messaggio,n) me li stampa tranquillamente, ma non capisco perchè mi da errore solo per la stringa testo
Innanzitutto non puoi definire delle funzioni dentro altre funzioni. Sposta random(), PercentualeOrario() ed ElencoMessaggi() fuori da main() (i typedef vanno messi prima di essere usati, quindi sposta anche loro). Sembra che GCC permetta funzioni annidate come estensione, ma non è standard C; quando compili usa il comando:
Inoltre usi delle variabili locali della funzione main() dentro altre ElencoMessaggi(), ad esempio 'dim'. L'errore che dici tu a me non lo segnala, comincia a correggere questi e poi vediamo.
gcc -std=c89 -pedantic -Wall nome_file.c
Inoltre usi delle variabili locali della funzione main() dentro altre ElencoMessaggi(), ad esempio 'dim'. L'errore che dici tu a me non lo segnala, comincia a correggere questi e poi vediamo.
Ok, ora ho compilato secondo i punti che mi hai detto, però l'errore me lo da lo stesso.
ecco il codice
ecco il codice
#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 50 typedef struct{ int giorno; int mese; }tdata; typedef struct{ int ore; int minuti; }torario; typedef struct{ tdata data; torario orario; int numero; char testo[200]; }tmessaggi; tmessaggi messaggio[N]; //Definisco una struttura dati opportuna per la funzione ElencoMessaggi (visto che non può restituire un array ma può restituire una struct) typedef struct{ tmessaggi messaggio[N]; int num; }ris; //Funzione random numeri int random(int min,int max){ int ran; ran=rand()%(max+min-1)+min; return ran; } // Funzione percentuale orario: int PercentualeOrario(tmessaggi a[],int ore, int min,int dim){ float percentuale,somma=0; int i; for(i=0;i<dim;i++){ if(a[i].orario.ore>ore){ somma+=1; } else{ if(a[i].orario.ore==ore && a[i].orario.minuti>min){ somma+=1; }else{somma+=0;} } } percentuale=(somma/dim)*100; return percentuale; } //FUnzione elenco ris ElencoMessaggi(tmessaggi a[],int numerotel,int dim){ ris r; int i; r.num=0; for(i=0;i<dim;i++){ if(numerotel==a[i].numero){ r.messaggio[r.num]=a[i]; r.num++; } } return r; } int main(int argc, char *argv[]) { //Invoco le funzioni int random(int min,int max); int PercentualeOrario(tmessaggi a[],int ore, int min); ris ElencoMessaggi(tmessaggi a[],int numerotel); //Comincio l'esercizio int i=0,dim; char termina='n'; while(i<N && termina=='n'){ printf("\t *** Ciao, inserisci i dati messaggio nr. %d ***",i+1); messaggio[i].data.giorno=random(1,31); messaggio[i].data.mese=random(1,12); printf("\n\n ore:"); scanf("%d",&messaggio[i].orario.ore); while(messaggio[i].orario.ore<0 || messaggio[i].orario.ore>23){ printf("\nIl valore delle ore deve essere compreso tra 0 e 23.\nInserisci un nuovo valore per le ore:"); scanf("%d",&messaggio[i].orario.ore); } printf("\n\n minuti:"); scanf("%d",&messaggio[i].orario.minuti); while(messaggio[i].orario.minuti<0 || messaggio[i].orario.minuti>59){ printf("\nIl valore dei minuti deve essere compreso tra 0 e 59.\nInserisci un nuovo valore per i minuti:"); scanf("%d",&messaggio[i].orario.minuti); } printf("\nNumero di telefono:"); scanf("%d",&messaggio[i].numero); printf("\nTesto del messaggio:"); fflush(stdin);gets(messaggio[i].testo); printf("\n Terminare l'inserimento?s/n:"); scanf("%c",&termina); i++; dim=i; } //STampo i campi messaggio: printf("\t *** Elenco messaggi: ***\n\n"); for(i=0;i<dim;i++){ printf(" %d \t %d \t %d \t %d \t %d \t %s \n\n",messaggio[i].data.giorno,messaggio[i].data.mese,messaggio[i].orario.ore,messaggio[i].orario.minuti,messaggio[i].numero,messaggio[i].testo); } // Inserendo un orario voglio sapere che percentuale di messaggi sono stati ricevuti dopo tale orario int o,m; printf("\n Inserire l'orario dopo il quale si vuole conoscere la percentuale di sms ricevuti:\nore:"); scanf("%d",&o); printf("\n minuti:"); scanf("%d",&m); printf("La percentuale di sms mandati dopo tale ora e: %d per cento\n\n",PercentualeOrario(messaggio,o,m,dim)); //Voglio ottenere l'elenco dei messaggi ricevuti dallo stesso numero int n; printf("Inserire il numero di telefono:"); scanf("%d",&n); printf("I messaggi mandati da tale numero sono:\n\n"); for(i=0;i<dim;i++){ printf(" %d \t %d \t %d \t %d \t %s \n\n",ElencoMessaggi(messaggio,n).messaggio[i].data.giorno,ElencoMessaggi(messaggio,n).messaggio[i].data.mese,ElencoMessaggi(messaggio,n).messaggio[i].orario.ore,ElencoMessaggi(messaggio,n).messaggio[i].orario.minuti,ElencoMessaggi(messaggio,n).messaggio[i].testo); } system("PAUSE"); return 0; }
"claudio86":
Innanzitutto non puoi definire delle funzioni dentro altre funzioni. Sposta random(), PercentualeOrario() ed ElencoMessaggi() fuori da main() (i typedef vanno messi prima di essere usati, quindi sposta anche loro). Sembra che GCC permetta funzioni annidate come estensione, ma non è standard C; quando compili usa il comando:
gcc -std=c89 -pedantic -Wall nome_file.c
Inoltre usi delle variabili locali della funzione main() dentro altre ElencoMessaggi(), ad esempio 'dim'. L'errore che dici tu a me non lo segnala, comincia a correggere questi e poi vediamo.
[OT] Va bene che gcc è rimasto indietro ma sono usciti 2 standard dopo l'89 (1999 e 2011). Seppur il c11 sia per certi versi uno standard migliore del c99 direi che usare lo standard c99 sia meglio anche in gcc (puoi definire le variabili dove vuoi per esempio). Tanto quello che gcc non implementa del c99 probabilmente non lo useresti.
In ogni caso, clang+llvm e altri compilatori lavorano di default con il c99.
[/OT]
A me da errori ben diversi con clang. Dopo provo pelles C e vedo che mi dice.
Queste linee nel main
vanno eliminate.
Inoltre in questo printf
la funzione ElencoMessaggi richiede 3 argomenti e tu ne hai messi solo 2. Il terso dovrebbe essere dim.
[Edit] Ok, con pelles compila con le correzioni sopra e sembra funzionare meglio il programma. In ogni caso dovresti sostituire quel gets, chiunque te lo abbia insegnato è un incompetente: è DEPRECATO e considerato INSICURO da chiunque. Va sostituito con fgets.
Queste linee nel main
//Invoco le funzioni int random(int min,int max); int PercentualeOrario(tmessaggi a[],int ore, int min); ris ElencoMessaggi(tmessaggi a[],int numerotel);
vanno eliminate.
Inoltre in questo printf
printf(" %d \t %d \t %d \t %d \t %s \n\n", ElencoMessaggi(messaggio,n).messaggio[i].data.giorno, ElencoMessaggi(messaggio,n).messaggio[i].data.mese, ElencoMessaggi(messaggio,n).messaggio[i].orario.ore, ElencoMessaggi(messaggio,n).messaggio[i].orario.minuti, ElencoMessaggi(messaggio,n).messaggio[i].testo);
la funzione ElencoMessaggi richiede 3 argomenti e tu ne hai messi solo 2. Il terso dovrebbe essere dim.
[Edit] Ok, con pelles compila con le correzioni sopra e sembra funzionare meglio il programma. In ogni caso dovresti sostituire quel gets, chiunque te lo abbia insegnato è un incompetente: è DEPRECATO e considerato INSICURO da chiunque. Va sostituito con fgets.
Allora, innanzitutto alle linee 81, 82, 83, dopo il commento "Invoco le funzioni", hai ripetuto i prototipi delle funzioni random(), PercentualeOrario() e ElencoMessaggi(), oltretutto sbagliati poiché alle ultime due manca il parametro 'dim'. Le funzioni sono già definite prima del main() quindi non c'è bisogno di ripetere i prototipi, inoltre metterli dentro una funzione (il main()) è una pessima pratica.
Infine alla linea 158 chiami la funzione ElencoMessaggi() passando soli due parametri, mentre ne servono tre (manca 'dim').
Inoltre sarebbe molto più chiaro usare delle variabili:
Comunque non ho ancora visto l'errore a cui ti riferivi all'inizio. Sarebbe meglio se tu postassi l'esatto messaggio (che contiene anche la linea relativa, così è più semplice capire dov'è l'errore).
@vict85
Io non programmo in C, ma vedo sempre che tutti consigliano di usare gcc -ansi -pedantic, che dovrebbe essere equivalente a -std=c89. Fosse per me io farei sempre -std=c++11 (ancora poco supportato però). GCC credo che abiliti di default le sue estensioni, quindi sarebbe meglio dirgli di usare uno standard vero, c89 o c99 che sia.
Edit:
L'edit di vict85 mi ha fatto notare un altro errore:
è espressamente vietato dallo standard (o meglio, ha risultato indefinito quindi è il caso di non usarlo mai). L'avevo sottolineato qualche giorno fa in questo thread.
Infine alla linea 158 chiami la funzione ElencoMessaggi() passando soli due parametri, mentre ne servono tre (manca 'dim').
Inoltre sarebbe molto più chiaro usare delle variabili:
ris risultato = ElencoMessaggi(messaggio, n, dim); for(i=0;i<dim;i++){ int giorno = risultato.messaggio[i].data.giorno; int mese = risultato.messaggio[i].data.mese; int ore = risultato.messaggio[i].orario.ore; int minuti = risultato.messaggio[i].orario.minuti; const char * testo = risultato.messaggio[i].testo; printf(" %d \t %d \t %d \t %d \t %s \n\n", giorno, mese, ore, minuti, testo); }
Comunque non ho ancora visto l'errore a cui ti riferivi all'inizio. Sarebbe meglio se tu postassi l'esatto messaggio (che contiene anche la linea relativa, così è più semplice capire dov'è l'errore).
@vict85
Io non programmo in C, ma vedo sempre che tutti consigliano di usare gcc -ansi -pedantic, che dovrebbe essere equivalente a -std=c89. Fosse per me io farei sempre -std=c++11 (ancora poco supportato però). GCC credo che abiliti di default le sue estensioni, quindi sarebbe meglio dirgli di usare uno standard vero, c89 o c99 che sia.
Edit:
L'edit di vict85 mi ha fatto notare un altro errore:
fflush(stdin);
è espressamente vietato dallo standard (o meglio, ha risultato indefinito quindi è il caso di non usarlo mai). L'avevo sottolineato qualche giorno fa in questo thread.
"claudio86":
@vict85
Io non programmo in C, ma vedo sempre che tutti consigliano di usare gcc -ansi -pedantic, che dovrebbe essere equivalente a -std=c89. Fosse per me io farei sempre -std=c++11 (ancora poco supportato però). GCC credo che abiliti di default le sue estensioni, quindi sarebbe meglio dirgli di usare uno standard vero, c89 o c99 che sia.
Beh, anche io uso principalmente il C++, non ho ancora però avuto modo di usare il C++11... Intendevo soltanto di mettere -std=c99 al posto di c89. Semplicemente non capisco perché la gente si ostini a consigliare il c89 quando il c99 rende "ufficiali" alcune estensioni già presenti in alcuni compilatori. La poca diffusione del c99 è legata alla sua rottura con il c++ anche se gli 11 si sono un po' riavvicinati mi sembra (non sono un esperto anche se ho lo standard sul pc). A dire il vero il c99 da una parte si avvicina e da una parte rompe nel senso che ha reso possibile alcune cose che prima potevi fare solo sul c++ ma ha anche implementato diversamente alcune cose.
Se ti interessa lo standard c11 (o meglio l'ultimo draft prima dello standard) lo trovi come n1570. http://www.open-std.org/jtc1/sc22/wg14/ ... /n1570.pdf
@vict85
In effetti lo standard 89 è abbastanza scomodo, con la dichiarazione delle variabili in testa al blocco e niente commenti C++. Allora diciamo di compilare con gcc -std=c99 -pedantic -Wall -Wextra file.c (e -Weverything se si usa CLang e si ha tempo da perdere).
Ho dato un'occhiata alla pagina di Wikipedia su C11 e quasi tutte le voci credo siano state incluse anche in C++11, quindi il sottoinsieme comune sembrerebbe riavvicinarsi all'intero C11.
Un paio di articoli sul C++11: uno e due.
In effetti lo standard 89 è abbastanza scomodo, con la dichiarazione delle variabili in testa al blocco e niente commenti C++. Allora diciamo di compilare con gcc -std=c99 -pedantic -Wall -Wextra file.c (e -Weverything se si usa CLang e si ha tempo da perdere).
Ho dato un'occhiata alla pagina di Wikipedia su C11 e quasi tutte le voci credo siano state incluse anche in C++11, quindi il sottoinsieme comune sembrerebbe riavvicinarsi all'intero C11.
Un paio di articoli sul C++11: uno e due.
Bè innanzitutto grazie a tutti per le dritte, soprattutto a Claudio.
capisco l'avvertimento riguardo alla funzione gets() e ti ringrazio, sta di fatto che inserendo fgets() il testo in output non mi viene nemmeno richiesto, che abbia sbagliato qualcosa nella definizione?
Comunque ecco il codice completo:
Ho trovato poi estremamente comoda la procedura
Ma come hai potuto vedere coi puntatori ho poca dimestichezza...per caso vi è un'alternativa?
Altrimenti ti sarei grato se mi spieghi cosa è stato fatto.
Un'ultima postilla: nell'output della funzione ElencoMessaggi vengono compilati 0 nei campi nulli, per far in modo di eliminare gli zeri ho pensato di modificare in questa maniera la funzione, inserendo un puntatore in modo che modifica istantaneamente la variabile dim, però ovviamente non sono in grado di farla funzionare:
qualche consiglio?
ancora Grazie
capisco l'avvertimento riguardo alla funzione gets() e ti ringrazio, sta di fatto che inserendo fgets() il testo in output non mi viene nemmeno richiesto, che abbia sbagliato qualcosa nella definizione?
Comunque ecco il codice completo:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 50 typedef struct{ int giorno; int mese; }tdata; typedef struct{ int ore; int minuti; }torario; typedef struct{ tdata data; torario orario; int numero; char testo[200]; }tmessaggi; tmessaggi messaggio[N]; //Definisco una struttura dati opportuna per la funzione ElencoMessaggi (visto che non può restituire un array ma può restituire una struct) typedef struct{ tmessaggi messaggio[N]; int num; }ris; //Funzione random numeri int random(int min,int max){ int ran; ran=rand()%(max+min-1)+min; return ran; } // Funzione percentuale orario: int PercentualeOrario(tmessaggi a[],int ore, int min,int dim){ float percentuale,somma=0; int i; for(i=0;i<dim;i++){ if(a[i].orario.ore>ore){ somma+=1; } else{ if(a[i].orario.ore==ore && a[i].orario.minuti>min){ somma+=1; }else{somma+=0;} } } percentuale=(somma/dim)*100; return percentuale; } //FUnzione elenco ris ElencoMessaggi(tmessaggi a[],int numerotel,int dim){ ris r; int i; r.num=0; for(i=0;i<dim;i++){ if(numerotel==a[i].numero){ r.messaggio[r.num]=a[i]; r.num++; } } return r; } //Invoco le funzioni int random(int min,int max); int PercentualeOrario(tmessaggi a[],int ore, int min); ris ElencoMessaggi(tmessaggi a[],int numerotel); int main(int argc, char *argv[]) { //Comincio l'esercizio int i=0,dim; char termina='n'; while(i<N && termina=='n'){ printf("\t *** Ciao, inserisci i dati messaggio nr. %d ***",i+1); messaggio[i].data.giorno=random(1,31); messaggio[i].data.mese=random(1,12); printf("\n\n ore:"); scanf("%d",&messaggio[i].orario.ore); while(messaggio[i].orario.ore<0 || messaggio[i].orario.ore>23){ printf("\nIl valore delle ore deve essere compreso tra 0 e 23.\nInserisci un nuovo valore per le ore:"); scanf("%d",&messaggio[i].orario.ore); } printf("\n\n minuti:"); scanf("%d",&messaggio[i].orario.minuti); while(messaggio[i].orario.minuti<0 || messaggio[i].orario.minuti>59){ printf("\nIl valore dei minuti deve essere compreso tra 0 e 59.\nInserisci un nuovo valore per i minuti:"); scanf("%d",&messaggio[i].orario.minuti); } printf("\nNumero di telefono:"); scanf("%d",&messaggio[i].numero); printf("\nTesto del messaggio:"); fgets(messaggio[i].testo,N,stdin); printf("\n Terminare l'inserimento?s/n:"); scanf("%c",&termina); i++; dim=i; } //STampo i campi messaggio: printf("\t *** Elenco messaggi: ***\n\n"); for(i=0;i<dim;i++){ printf(" %d \t %d \t %d \t %d \t %d \t %s \n\n",messaggio[i].data.giorno,messaggio[i].data.mese,messaggio[i].orario.ore,messaggio[i].orario.minuti,messaggio[i].numero,messaggio[i].testo); } // Inserendo un orario voglio sapere che percentuale di messaggi sono stati ricevuti dopo tale orario int o,m; printf("\n Inserire l'orario dopo il quale si vuole conoscere la percentuale di sms ricevuti:\nore:"); scanf("%d",&o); printf("\n minuti:"); scanf("%d",&m); printf("La percentuale di sms mandati dopo tale ora e: %d per cento\n\n",PercentualeOrario(messaggio,o,m,dim)); //Voglio ottenere l'elenco dei messaggi ricevuti dallo stesso numero int n; printf("Inserire il numero di telefono:"); scanf("%d",&n); printf("I messaggi mandati da tale numero sono:\n\n"); ris risultato; risultato=ElencoMessaggi(messaggio,n,&dim); for(i=0;i<dim;i++){ int giorno = risultato.messaggio[i].data.giorno; int mese = risultato.messaggio[i].data.mese; int ore = risultato.messaggio[i].orario.ore; int minuti = risultato.messaggio[i].orario.minuti; const char * testo = risultato.messaggio[i].testo; printf(" %d \t %d \t %d \t %d \t %s \n\n", giorno, mese, ore, minuti, testo); } //for(i=0;i<dim;i++){ //printf(" %d \t %d \t %d \t %d \t %s \n\n",ElencoMessaggi(messaggio,n,dim).messaggio[i].data.giorno,ElencoMessaggi(messaggio,n,dim).messaggio[i].data.mese,ElencoMessaggi(messaggio,n,dim).messaggio[i].orario.ore,ElencoMessaggi(messaggio,n,dim).messaggio[i].orario.minuti,ElencoMessaggi(messaggio,n,dim).messaggio[i].testo); //} system("PAUSE"); return 0; }
Ho trovato poi estremamente comoda la procedura
const char * testo = risultato.messaggio[i].testo;
Ma come hai potuto vedere coi puntatori ho poca dimestichezza...per caso vi è un'alternativa?
Altrimenti ti sarei grato se mi spieghi cosa è stato fatto.
Un'ultima postilla: nell'output della funzione ElencoMessaggi vengono compilati 0 nei campi nulli, per far in modo di eliminare gli zeri ho pensato di modificare in questa maniera la funzione, inserendo un puntatore in modo che modifica istantaneamente la variabile dim, però ovviamente non sono in grado di farla funzionare:
ris ElencoMessaggi(tmessaggi a[],int numerotel,int*dim){ ris r; int i; r.num=0; for(i=0;i<dim;i++){ if(numerotel==a[i].numero){ r.messaggio[r.num]=a[i]; r.num++; } } *dim=&r.num; dim=*dim; return r; }
qualche consiglio?
ancora Grazie
Per l'fgets non devi mettere N come limite ma 200 che è la dimensione di testo. Per il resto in quella linea non vedo problemi, con cosa compili?
Non comprendo la tua domanda sul puntatore a char. Cosa è stato fatto dove? Ti riferisci al significato di quella linea di codice? Dici soltanto di memorizzare l'indirizzo dell'inizio dell'array nella variabile testo. Dopo di che lo potrai richiamare quando ti servirà.
Per l'ultima cosa non ne vedo lo scopo, se l'autore non ha inserito un dato giustamente la funzione non lo stampa. L'interfaccia dovrebbe avere un certo grado di uniformità. In ogni caso non ho capito cosa vuoi fare, eliminare i messaggi vuoti? Gli array non sono esattamente la migliore struttura dati per questo genere di operazioni.
Non comprendo la tua domanda sul puntatore a char. Cosa è stato fatto dove? Ti riferisci al significato di quella linea di codice? Dici soltanto di memorizzare l'indirizzo dell'inizio dell'array nella variabile testo. Dopo di che lo potrai richiamare quando ti servirà.
Per l'ultima cosa non ne vedo lo scopo, se l'autore non ha inserito un dato giustamente la funzione non lo stampa. L'interfaccia dovrebbe avere un certo grado di uniformità. In ogni caso non ho capito cosa vuoi fare, eliminare i messaggi vuoti? Gli array non sono esattamente la migliore struttura dati per questo genere di operazioni.
Compilo con DEV C++ 4.9.9.2
Ok quindi ricapitolando, utilizzando fgets( a , b , c)
a è il campo (o variabile) alla quale attribuisco il testo
b è il numero di caratteri che può assumere il testo
c rappresenta la lettura input di tastiera
corretto?
Bene, ora sarei curioso di conoscere meglio l'utilizzo di quel puntatore, mi chiedo:
perchè se avessi stampato la funzione in questo modo
Non mi avrebbe dato il risultato sperato, mentre utilizzando questa dicitura va bene?
Ok quindi ricapitolando, utilizzando fgets( a , b , c)
a è il campo (o variabile) alla quale attribuisco il testo
b è il numero di caratteri che può assumere il testo
c rappresenta la lettura input di tastiera
corretto?
Bene, ora sarei curioso di conoscere meglio l'utilizzo di quel puntatore, mi chiedo:
perchè se avessi stampato la funzione in questo modo
for(i=0;i<dim;i++){ stringa testo = risultato.messaggio[i].testo; printf(" %s \n\n" ,testo); }
Non mi avrebbe dato il risultato sperato, mentre utilizzando questa dicitura va bene?
for(i=0;i<dim;i++){ const char * testo = risultato.messaggio[i].testo; printf(" %s \n\n" ,testo); }
"ELWOOD":
Compilo con DEV C++ 4.9.9.2
Male. Faresti meglio ad usare qualcosa di questo decennio. Visual C++ Express, Code::Blocks o anche QtCreator.
Bene, ora sarei curioso di conoscere meglio l'utilizzo di quel puntatore
In C le stringhe non esistono, si usano array di caratteri per simularle. Un array è (quasi) un puntatore al suo primo elemento. In memoria c'è una sequenza di elementi e la variabile relativa a quell'array punta al primo. Ad esempio durante l'esecuzione del programma:
int main() { char hello[5] = "Ciao"; int a = 28; int b = a; int *pa = & a; int *pa2 = pa; char *h2 = hello; }
la memoria potrebbe avere questo contenuto (tralasciando il fatto che spesso la dimensione di un int è maggiore di quella di un char):
Indirizzo, Contenuto ... 0034, 'C' // Il primo elemento dell'array, da qualche parte in memoria 0035, 'i' 0036, 'a' 0037, 'o' 0038, 0 // Le stringhe hanno 0 come terminatore ... // Quando viene chiamata la funzione main() vengono create le sue variabili: 0637, 0034 // La variabile "hello'", che contiene l'indirizzo del primo elemento dell'array 0638, 28 // La variabile "a" 0639, 28 // La variabile "b", copia di "a" 0640, 0638 // La variabile "pa", che contiene l'indirizzo di "a" 0641, 0638 // La variabile "pa2", copia di "pa" 0642, 0034 // La variabile "h2", contiene l'indirizzo di "hello" (vedi dopo) ...
Gli array non sono esattamente puntatori al loro primo elemento, ma possono essere convertiti in puntatori al loro primo elemento senza problemi (si dice che "decadono" in puntatori). Tra le differenze ci sono: gli array hanno come informazione aggiuntiva il numero dei loro elementi (solo durante la compilazione, una volta in esecuzione sono identici a puntatori lisci), i puntatori no (possono puntare qualsiasi indirizzo, anche non relativo ad un array); e gli array non possono essere assegnati, i puntatori sì:
char uno[4] = "Uno"; char due[4] = "Due"; uno = due; // Errore char * tre = uno; // Ok
Quindi per riferirti ad un array ti conviene usare un puntatore:
const char * testo = risultato.messaggio[i].testo; int ore = risultato.messaggio[i].orario.ore;
Nota che il puntatore è dichiarato "const" mentre l'intero no.
"ore" è una copia della variabile dentro lo struct, quindi se anche la modificassi il valore di "risultato.messaggio[ i].orario.ore" non cambierebbe. "testo" è sempre una copia della variabile dentro lo struct, ma è un puntatore quindi se modificassi la memoria all'indirizzo puntato da "testo" cambierebbe anche quella all'indirizzo puntato da "risultato.messaggio[ i].testo" (puntano allo stesso indirizzo, vedi esempio sulla memoria sopra).
Usando "const" rendi chiedi al compilatore di proibire modifiche alla memoria puntata da "testo".
Bè grazie davvero per la tua pazienza.
sperando di avercene capito qualcosina di più ti chiedo:
se non si avesse dichiarato const prima della variabile puntatore, cosa sarebbe cambiato?
Il fatto di scrivere:
senza const che cosa sarebbe cambiato?
Vediamo se ho capito:
Il testo viene sostanzialmente immagazzinato in un array di N dimensioni, in cui in ogni elemento dell'array viene immagazzinato un carattere del testo.
il puntatore *testo assume dimensione diversa ogni volta che si effettua il ciclo for per cui va a leggere ogni elemento dell'array testo. Però assumendo ad ogni ciclo un valore diverso, non otterrò il testo definito nella variabile struct.
Mentre con "const" legge solo l'array definito per il valore i del ciclo for
sperando di avercene capito qualcosina di più ti chiedo:
se non si avesse dichiarato const prima della variabile puntatore, cosa sarebbe cambiato?
Il fatto di scrivere:
for(i=0;i<dim;i++){ char * testo = risultato.messaggio[i].testo; printf(" %s \n\n" ,testo); }
senza const che cosa sarebbe cambiato?
Vediamo se ho capito:
Il testo viene sostanzialmente immagazzinato in un array di N dimensioni, in cui in ogni elemento dell'array viene immagazzinato un carattere del testo.
il puntatore *testo assume dimensione diversa ogni volta che si effettua il ciclo for per cui va a leggere ogni elemento dell'array testo. Però assumendo ad ogni ciclo un valore diverso, non otterrò il testo definito nella variabile struct.
Mentre con "const" legge solo l'array definito per il valore i del ciclo for
"ELWOOD":
se non si avesse dichiarato const prima della variabile puntatore, cosa sarebbe cambiato?
Il fatto di scrivere:
Per questo particolare esempio usare "const" o meno non avrebbe fatto nessuna differenza, perché non tenti di modificare "testo":
for(i=0;i<dim;i++){ char * testo = risultato.messaggio[i].testo; printf(" %s \n\n", testo); // Ok, non modifichi "testo", lo leggi e basta // Cambiamo la terza lettera di testo in 't': testo[2] = 't'; // Ok, puoi modificare la memoria puntata da "testo" }
for(i=0;i<dim;i++){ const char * testo = risultato.messaggio[i].testo; printf(" %s \n\n", testo); // Ok, non modifichi "testo", lo leggi e basta // Cambiamo la terza lettera di testo in 't': testo[2] = 't'; // Errore di compilazione, non puoi modificare la memoria // puntata da "testo" perché è dichiarato "const" }
In generale se non ti serve modificare una variabile dichiarala sempre const, per prevenire modifiche accidentali.
il puntatore *testo assume dimensione diversa ogni volta che si effettua il ciclo
Assume valore diverso ad ogni iterazione. Ad ogni iterazione cambia il valore di "i" (ovviamente) e "testo" assume come valore l'indirizzo del primo elemento di "risultato.messaggio.testo".
"claudio86":
Per questo particolare esempio usare "const" o meno non avrebbe fatto nessuna differenza, perché non tenti di modificare "testo"
Per cui non avrei potuto utilizzare una variabile del tipo "char testo[20]"
"ELWOOD":
Per cui non avrei potuto utilizzare una variabile del tipo "char testo[20]"
No perché ad un array non puoi assegnare un valore (array = qualcosa). Al massimo puoi inizializzarlo ad una costante letterale:
char testo[20] = "Costante letterale"; // Ok char testo[20] = {'C', 'o', 's', 't', 'a', 'n', 't', 'e'}; // Ok char testo[20] = altroArrayChar20; // Errore, non puoi inizializzarlo // con una variabile testo = "Altro valore letterale"; // Errore, non è un'inizializzazione
Avresti potuto usare char * testo:
for(i=0;i<dim;i++){ const char * testo = risultato.messaggio[i].testo; // Ok, ma non potrai modificare // il contenuto dell'array, printf(" %s \n\n", testo);
for(i=0;i<dim;i++){ char * testo = risultato.messaggio[i].testo; // Ok, potrai anche modificare // il contenuto dell'array, printf(" %s \n\n", testo);
Ok quindi se ho capito utilizzo il puntatore perchè mi legge la memoria dell'array (cioè il testo), con una variabile normale non avrei potuto farlo perchè una variabile normale non può assumere l'aspetto di un array
"ELWOOD":
Ok quindi se ho capito utilizzo il puntatore perchè mi legge la memoria dell'array (cioè il testo), con una variabile normale non avrei potuto farlo perchè una variabile normale non può assumere l'aspetto di un array
Non proprio, il problema sta nel fatto che in C un'array non è una variabile ma una successione di variabili. Inoltre il C non implementa l'uguaglianza tra array. Quindi, al contrario di altri linguaggi char a[] = b non ha alcun senso in C. In compenso potresti usare la funzione di libreria strcpy.
Il fatto però è che usare i puntatori evita la copia e minimizza l'uso di memoria aggiuntivo. Per intenderci un puntatore è solo qualcosa che informa sulla posizione in memoria di qualcos'altro. Nel caso degli array o delle stringhe informa su dove incominciare a leggere.