Driverfury (Normal User)
Rookie
Messaggi: 45
Iscritto: 21/09/2011
|
Ciao a tutti, stavo creando una rubrica in C quando andando a compilare in una funzione c'è stato l'errore: "incompatible types in return". Ecco il file sorgente:
Codice sorgente - presumibilmente C++ |
#include <stdio.h> #include <stdlib.h> #include <string.h> // Variabili e costanti globali const int MAX_CON = 500; // Costante che sta ad indicare il massimo numero di contatti della rubrica // Struttura: Contatto struct contact { char *name; char *surname; char *number; char *address; }; // Prototipi di funzioni struct contact returnContacts(char *fileName); int main() { char *fname = "rubrica.txt" struct contact c[MAX_CON]; c = returnContacts(fname); } // Funzione che ritorna una struttura di contatti o un array di contatti struct contact returnContacts(char *fileName) { FILE *fp; // Puntatore a file struct contact c[MAX_CON]; // Variabile di tipo struttura "contact" int i=0; // Contatore if(!(fp=fopen(fileName, "r"))) // Se non riesce ad aprire il file in modalità di scrittura { printf("\nErrore durante l'apertura del file \"%s\" in modalita' lettura.\n", fileName); return; } while(fscanf(fp, "%s %s %s %s\n", c[i].name, c[i].surname, c[i].number, c[i].address)>0) /* Fin quando riesce a leggere da file più di 0 Byte */ { i++; } fclose(fp); // Chiudo il file return c; // Questo è l'errore!!! }
|
L'errore c'è quando ritorno "c" dalla funzione returnContacts(). Mi potete aiutare a farmi perchè c'è l'errore?
|
|
HeDo (Founder Member)
Guru^2
Messaggi: 2765
Iscritto: 21/09/2007
|
allora, a parte l'errore sintattico sulla dichiarazione della funzione che dovrebbe essere "struct contact *", c'è un gravissimo errore semantico che non farà funzionare nulla e sono sicuro che non ci sbatteresti la testa per giorni.
non si può ritornare un array statico da una funzione, il motivo è che l'area di memoria dove è allocato va fuori scopo dopo il ritorno della funzione. per risolvere il problema ci sono due strade, la prima è allocare l'array con malloc, ovvero far si che risieda nell'heap e non nello stack. il contro di questa opzione è che ti devi ricordare di chiamare free sull'array dopo che hai utilizzato i dati nel main, altrimenti ti ritroverai con un memory leak.
la seconda strada, quella che io consiglio, è passare l'array di output come parametro della funzione e riempirlo all'interno della stessa. in questo modo la funzione non si deve occupare dell'allocazione della memoria ma è gestito tutto dal main.
|
|
Driverfury (Normal User)
Rookie
Messaggi: 45
Iscritto: 21/09/2011
|
Innanzitutto grazie. Ho provato a modificare il codice secondo i tuoi consigli:
Codice sorgente - presumibilmente C++ |
#include <stdio.h> #include <stdlib.h> #include <string.h> // Variabili e costanti globali const int MAX_CON = 500; // Costante che sta ad indicare il massimo numero di contatti della rubrica // Struttura: Contatto struct contact { char *name; char *surname; char *number; char *address; }; // Prototipi di funzioni struct contact * returnContacts(char *fileName, struct contact c[MAX_CON]); int main() { char *fname = "rubrica.txt" struct contact c[MAX_CON]; c = returnContacts(fname, c); } // Funzione che ritorna un array di contatti struct contact * returnContacts(char *fileName, struct contact c[MAX_CON]) { FILE *fp; // Puntatore a file int i=0; // Contatore if(!(fp=fopen(fileName, "r"))) // Se non riesce ad aprire il file in modalità di scrittura { printf("\nErrore durante l'apertura del file \"%s\" in modalita' lettura.\n", fileName); return; } while(fscanf(fp, "%s %s %s %s\n", c[i].name, c[i].surname, c[i].number, c[i].address)>0) /* Fin quando riesce a leggere da file più di 0 Byte */ { i++; } fclose(fp); // Chiudo il file return c; // Ritorna il contatto o l'array di contatti }
|
... Purtroppo l'errore è lo stesso... potresti aiutarmi più nel dettaglio?
Ultima modifica effettuata da Driverfury il 19/12/2011 alle 16:34 |
|
nessuno (Normal User)
Guru^2
Messaggi: 6404
Iscritto: 03/01/2010
|
Non hai proprio seguito tutti i consigli ... la funzione NON deve restituire nulla dato che lavora con il vettore passato come parametro.
Quindi sarà di tipo
void
e non
struct contact *
la chiamerai con
returnContacts(fname, c);
e non ci sarà la riga
return c;
P.S. In merito alla tua firma, qual è la Domanda ?
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità. |
|
Bonny (Member)
Expert
Messaggi: 437
Iscritto: 24/04/2009
|
non poi passare il vettore con la sua dimensione come parametro di una funzione....
Codice sorgente - presumibilmente C/C++ |
struct contact * returnContacts(char *fileName, struct contact c[MAX_CON]);
|
devi farlo cosi
Codice sorgente - presumibilmente C++ |
struct contact * returnContacts(char *fileName, struct contact c[]); //or struct contact * returnContacts(char *fileName, struct contact *c);
|
il vettore viene passato per riferimento... ovvero viene passato il puntatore alla prima allocazione di memoria del vettore
adesso capisci perchè Hedo ti ha consigliato di passarlo come parametro?
tutte le operazioni (assegnamento ecc..) che fai sul vettore, al termine della funzione restano "persistenti" in esso segue che non serve fare il return, quindi diventa:
Codice sorgente - presumibilmente C/C++ |
void returnContacts(char *fileName, struct contact c[]);
|
Ultima modifica effettuata da Bonny il 19/12/2011 alle 16:49 |
|
Driverfury (Normal User)
Rookie
Messaggi: 45
Iscritto: 21/09/2011
|
Postato originariamente da nessuno:
Non hai proprio seguito tutti i consigli ... la funzione NON deve restituire nulla dato che lavora con il vettore passato come parametro.
Quindi sarà di tipo
void
e non
struct contact *
la chiamerai con
returnContacts(fname, c);
e non ci sarà la riga
return c;
P.S. In merito alla tua firma, qual è la Domanda ? |
Sì, è vero avevo interpretato male quanto citato da Hedo. Grazie mille nessuno, sei sempre molto disponibile e pronto ad aiutare. Ultima modifica effettuata da Driverfury il 29/08/2015 alle 1:51 |
|
Driverfury (Normal User)
Rookie
Messaggi: 45
Iscritto: 21/09/2011
|
Comunque ho modificato il codice come mi avete consigliato ma l'applicazione si blocca e si chiude. Premetto che il file "rubrica.txt" esiste. Ecco come ho modificato il codice:
Codice sorgente - presumibilmente C++ |
#include <stdio.h> #include <stdlib.h> #include <string.h> // Variabili e costanti globali const int MAX_CON = 500; // Costante che sta ad indicare il massimo numero di contatti della rubrica // Struttura: Contatto struct contact { char *name; char *surname; char *number; char *address; }; // Prototipi di funzioni void returnContacts(char *fileName, struct contact c[]); int main() { char *fname = "rubrica.txt" struct contact c[MAX_CON]; returnContacts(fname, c); } // Procedura che assegna un array di contatti void returnContacts(char *fileName, struct contact c[]) { FILE *fp; // Puntatore a file int i=0; // Contatore if(!(fp=fopen(fileName, "r"))) // Se non riesce ad aprire il file in modalità di scrittura { printf("\nErrore durante l'apertura del file \"%s\" in modalita' lettura.\n", fileName); return; } while(fscanf(fp, "%s %s %s %s\n", c[i].name, c[i].surname, c[i].number, c[i].address)>0) /* Fin quando riesce a leggere da file più di 0 Byte */ { i++; } fclose(fp); // Chiudo il file }
|
|
|
nessuno (Normal User)
Guru^2
Messaggi: 6404
Iscritto: 03/01/2010
|
Postato originariamente da Driverfury:
Comunque ho modificato il codice come mi avete consigliato ma l'applicazione si blocca e si chiude. |
Per il futuro, il fatto che un'applicazione venga corretta (e vengano eliminati gli errori di compilazione) non significa che funzioni quando venga eseguita e non ci possano essere "altri" errori (a runtime appunto).
Il problema del tuo codice è causato dal fatto che hai utilizzato, nella struttura, dei puntatori a char e li hai utilizzati direttamente "senza allocare lo spazio" per ogni stringa. Questo causa (almeno) un crash dell'applicazione (come capita a te).
P.S. Per la firma, ok ... de gustibus ...
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità. |
|
TheKaneB (Member)
Guru^2
Messaggi: 1792
Iscritto: 26/06/2009
|
per dovere di cronaca, in C le funzioni possono ritornare anche intere struct, non per forza puntatori ad esse. In tal caso il compilatore infila un memcpy a tradimento, risolvendo tra l'altro il problema di allocazione della memoria per una singola struct (che introduce overhead e frammentazione dell'heap).
Questa era una limitazione Pre-ANSI ISO C89, mi sorprende che qualcuno se ne ricordi ancora O_o''
Io avevo 3 anni quando hanno sistemato questo problema
Ultima modifica effettuata da TheKaneB il 19/12/2011 alle 20:17 |
|