Newsgroup: it.comp.lang.c
Titolo: problemi scrivere e leggere da file

Ciao.
Mi sto' esercitando a scrivere programmi in linguaggio c.
Ho questo problema:
una funzione mi legge i dati scritti sul file,l'altra va a scriverli.Dopo
aver portato a termine una scrittura sul file, quando vado a leggere, mi
ritrovo un output fatto di tanti caratteri strani, che seguono i dati.
Non posto il codice perche' facendo un taglia e incolla da visual c viene in
un modo molto fastidioso da leggere.
Grazie a tutti

.. .credo dovresti postare la parte che non funziona . .
 in ogni modo ..--> credo che tu salvi e carichi nel file l'indirizzo
di mem di qualche puntatore o qualcos'altro al posto di numeri o parole.
Ciao
HS_
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 ritrovo un output fatto di tanti caratteri strani, che seguono i dati.
Puo' essere un miliardo di cose ! Senza codice e' veramente impossibile
rispondere.
1) Comunque controlla di aprire il file in modalita' testo o binaria a
seconda di cosa ci scrivi dentro (spesso e' uno dei problemi).
2) Controlla di aver chiuso il file dopo averlo scritto e di riaprirlo
prima di leggere.
g.

Questo e il codice delle funzioni.Non maltrattatemi sto' imparando.Se potevo
inviare un allegato era meglio ho cercato di ordinarlo il piu'
possibile.Penso che sia un errore banale pero' non riesco a capire dove
sbaglio.
Grazie a tutti.
void leggi(struct contribuenti contr[],char *filename)
{
   FILE *pf;
   struct contribuenti *p_contr;                       //Puntatore ad
unastruttura di
                                       tipo contribuenti
   char buffer[MAX_LENGHT],*p_line;
   p_contr=contr;//Faccio puntare p_contr all'array di
                          struct contr
   if((pf=fopen(filename,"r"))==NULL)
     printf("Errore nell'apertura del file\n");
   while(!feof(pf)) //Esegue il ciclo finche' non
                             viene letto il carattere EOF
   {
      fgets(buffer,MAX_LENGHT,pf);//Leggi una riga e
                                                       memorizzala in buffer
      p_line=buffer; //p_linee punta a buffer
      if(*p_line==' ') p_line++; file://Se *p_linee e' uguale al
                                   carattere blanck vine incrementato
                    p_linee(ora punta al secondo char di buffer)
        strcpy(buffer,p_line); //Nel caso la linea lettainizi con
                                      un blanck questo viene eliminato
      /*p_line=buffer+(strlen(buffer)-1);//Faccio puntare
                                 p_line al penultimo char della linea
      if(*p_line=='\n') *p_line=='\0';
      strcpy(buffer,p_line);//Copio p_line in buffer
      p_line=buffer; //Ora p_line punta al primo char di
                            buffer*/
sscanf(buffer,"%s%s%d%d",p_contr->lstname,p_contr->frtname,&p_contr->t_pag,&
p_contr->t_dov);//Memorizzo la linea letta da fgets(buffer) nei vari
elementi dell'array di strutture
      p_contr++;//Incremento il puntatore in modo da puntare al successivo
elemento dell'array di struct
   }
   fclose(pf);
}
void insert(char *nfile)
{
   FILE *pf;
   char temp[50]; file://buffer temporaneo x fgets, buffer
   int tp,td,count;//Vengono memorizzate tasse pagate e tasse dovute
   for(count=0;count<25;count++)
    temp[count]=0;
   if((pf=fopen(nfile,"a"))==NULL)
     printf("Errore nell'apertura del file\n");
   printf("Inserire nome\n");
   if((fgets(temp,25,stdin))==NULL)
     printf("Errore fgets\n");
   fprintf(pf,"%s\n",temp);
   fclose(pf);
}

                  // al successivo elemento dell'array di struct
e dove controlli che non vai a scrivere a zonzo per la memoria?
Ovvero come fai ad essere sicuro che nell'array passato alla
funzione entri tutto il contenuto del file?
C:\>iao Angelo


                  // elementi dell'array di strutture
Anche qui potrebbe esserci un errore
lstname, frtname sono array? In caso contrario, sono stati allocati?
Magari potevi anche inviare la dichiarazione della struttura
contribuenti, male non faceva.


 inviare un allegato era meglio ho cercato di ordinarlo il piu' possibile.
Non credo che quello che segue sia il meglio che puoi fare.
Hai provato ad aprire il file c con un altro editore (meglio
se un editore di solo testo) e a fare il copia e incolla da li,
invece che dall'editor integrato nel tuo compilatore ??
Gli errori possibili piu' comuni che mi vengono in mente:
1) L'errore piu' comune di tutti quando si opera con fgets:
    la fgets legge una riga alla volta e si ferma quando raggiunge
    il newline o la fine del file.
    Se l'ultima linea del file contiene un newline (perche' ad esempio
    tutte le linee sono state scritte come fprintf(f,"%s\n",var);)
    allora la fgets legge l'ultima riga fermandosi al newline e quindi
    NON SI ACCORGE CHE E' ARRIVATA IN FONDO AL FILE. Quindi il test
    del while successivo passa e uno esegue di nuovo una fgets su
    un file che di fatto e' easurito. Qui la fgets non legge nulla
    (e quindi non aggiorna il buffer) e uno in pratica si trova
    a leggere due volte l'ultima riga.
    Per ovviare a questo comportamento ci sono diversi modi
   (non so se c'e' ne e' uno standard)
    Il piu' brutale che mi viene in mente e' questo:
    FILE *f;
    f=fopen("pippo","r");
    while (!feof(f))
    {
       buf[0]=0;
       fgets(buf,LEN,f);
       if (buf[0]==0) break;
       ......
       .....
    }
    in questo modo mi accorgo di non aver letto nulla ed
    esco.
2) Altro errore possibile: hai allocato abbastanza record in contr[] ?
3) le stringhe nell'array di struct contr[] sono allocate dinamicamente
    (e in tal caso: le hai allocate prima di fare la sscanf ?)
     o staticamente ? (e in tal caso: hanno dimensione sufficiente ?)
4) Se qualcosa va storto (tipo errore apertura file) tu stampi un
messaggio e poi vai avanti lo stesso: questo non ha molto senso...
Poi una nota di carattere generale:
la sscanf e fscanf se ne infischiano allegramente di un
eventuale blank iniziale o del newline finale, quindi
tutta la papperdella col buffer e' useless.
potevi fare tutto piu' semplicemente cosi':
(ritornando anche il numero di record letti, che magari
potrebbe servire...) Naturalmente nell'ipotesi che
tu non debba allocare dinamicalmente lstname e frtname.
int  leggi(struct contribuenti contr[],char *filename)
{
   FILE *pf;
   int n=0;
   if((pf=fopen(filename,"r"))==NULL)
      {printf("Errore Apertura File\n"); exit(1);}
   while (4==fscanf(f,"%s%s%d%d",
                      contr[n].lstname,contr[n].frtname,
                      &contr[n].t_pag,&contr[n].t_dov))
          n++;
   fclose(pf);
   return n;
}
ciao,
g.

Ok quella di ricopiarla in un editor a parte e' stata grande.
Devo dire che non la conoscevo, altrimenti l'avrei usata.
Se non ho postato tutto il codice e' perche' mi vergognavo un po',
a mostrare quel casino.(pensate che ho anche cercato di ordinarlo)
Il programma gira bene,(per modo di dire, lo so' che ci sono parecchi
errori, se per favore potete evidenziarli, affinche' io possa imparare)cioe'
se vado ad aprire il file, nel quale io ho scritto i nomi, ll'output del
programma risulta corretto, mentre se vado a scriver un nome nel file
tramite programma, quando lo vado a riaprire mi ritrovo tanti di questi
caratteri.Grazie a tutti
 ?????????????????????????????????????????????
?????????????????????????????????????????????
?????????????????????????????????????????????
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAX_LENGHT 255 //Numero massimo di caratteri leggibili dal file o
numero mx di char delle linee lette dal file
#define MAX_LENGHT_NAME 255 //Numero massimo caratteri dei nomi contenuti
nella struttura contribuenti
#define MAX_STRUCT 50 //Numero massimo di elementi del vettore di strutture
contribuenti
struct contribuenti {
char lstname[MAX_LENGHT_NAME];
char frtname[MAX_LENGHT_NAME];
int t_pag;
int t_dov;
};
int count(char *filename);
void leggi(struct contribuenti contr[],char *filename);
void insert(char *nfile);
int main(void)
{
struct contribuenti c[10];
struct contribuenti *p;
char *fn="d:/pippo.len";
int n_linee,n;
p=c;
if(count(fn)==1)
printf("Non e' stato possibile aprire il file\n");
else
{
n_linee=count(fn);
printf("Numero linee= %d\n",n_linee);
}
leggi(c,fn);
for(n=0;n<=(n_linee-1);n++)
{
printf("%s %s %d %d\n",p->lstname,p->frtname,p->t_pag,p->t_dov);
p++;
}
insert(fn);
getch();
return 0;
}
//Funz alla quale viene passata una stringa(path+nomefile) ritorna il numero
di linee del file
int count(char *filename)
{
FILE *pf;
char temp[255]; //Appoggio temporaneo della lettura di fgets
int c_linee; //Variabile che indica il numero lineee
c_linee=1;
if((pf=fopen(filename,"r"))==NULL) //Se impossibile aprire file return 1
return 1; //Segnala che non e' stato possibile aprire il file
while(!feof(pf)) //Finche' non viene letto il carattere di fine file
{
fgets(temp,MAX_LENGHT,pf); //Leggi una riga dal file memorizzala in temp
if(temp[strlen(temp)-1]=='\n') //Se il penultimo char di temp uguale a '\n'
vuol dire che e' stato raggiunto il fine linea
c_linee++; //Incrementa il contatore di linee
}
fclose(pf);
return (c_linee-1); //Ritorna il numero di linee lette -1, in quanto
l'ultima linea del file e' EOF
}
/*La funzione leggi riceve come parametri il nome di un file e un array(50
elementi) di strutture tipo contribuenti, legge i vari capi
dal file e li memorizza nel rispettivo elemento della struttura
contribuenti.Ogni lenea del file corrisponde
ad un elemento dell'array di strutture */
void leggi(struct contribuenti contr[],char *filename)
{
FILE *pf;
struct contribuenti *p_contr; //Puntatore ad una struttura di tipo
contribuenti
char buffer[MAX_LENGHT],*p_line;
p_contr=contr;//Faccio puntare p_contr all'array di struct contr
if((pf=fopen(filename,"r"))==NULL)
printf("Errore nell'apertura del file\n");
while(!feof(pf)) //Esegue il ciclo finche' non viene letto il carattere EOF
{
fgets(buffer,MAX_LENGHT,pf);//Leggi una riga e memorizzala in buffer
p_line=buffer; //p_linee punta a buffer
if(*p_line==' ') p_line++; //Se *p_linee e' uguale al carattere blanck vine
incrementato p_linee(ora punta al secondo char di buffer)
strcpy(buffer,p_line); //Nel caso la linea letta inizi con un blanck questo
viene eliminato
/*p_line=buffer+(strlen(buffer)-1);//Faccio puntare p_line al penultimo char
della linea
if(*p_line=='\n') *p_line=='\0';//Se *p_line == char di nuova linea lo
sostituisco con il terminatore stringa
strcpy(buffer,p_line);//Copio p_line in buffer
p_line=buffer; //Ora p_line punta al primo char di buffer*/
sscanf(buffer,"%s%s%d%d",p_contr->lstname,p_contr->frtname,&p_contr->t_pag,&
p_contr->t_dov);//Memorizzo la linea letta da fgets(buffer) nei vari
elementi dell'array di strutture
p_contr++;//Incremento il puntatore in modo da puntare al successivo
elemento dell'array di struct
}
fclose(pf);
}
void insert(char *nfile)
{
FILE *pf;
char temp[5]; //buffer temporaneo x fgets, buffer
int tp,td,count;//Vengono memorizzate tasse pagate e tasse dovute
for(count=0;count<5;count++)
temp[count]=0;
if((pf=fopen(nfile,"a+"))==NULL)
printf("Errore nell'apertura del file\n");
printf("Inserire nome\n");
if((fgets(temp,5,stdin))==NULL)


 caratteri.Grazie a tutti
Il tuo programma contiene tanti e tali errori che non so se ho voglia
di mettermi a spulciarli tutti.
(Fra parentesi: non hai implementato i suggerimenti che ti ho dato nel
  mio messaggio precendente...)
Ti cito solo gli errori piu' grossi che mi saltano agli
occhi:
(si riassumono in 3 punti: insert sbagliata, count sbagliata, leggi 
sbagliata !!)
1) Il tuo metodo di leggere con fgets e' sbagliato e inutilmente 
complicato (i dettagli te li avevo gia' spiegati nel messaggio precedente).
2) come puoi pretendere di leggere correttamente quando la insert
inserisce solo una stringa mentre la tua funzione di lettura si
aspetta due stringhe e due interi in ogni riga ???? Cioe' se il
tuo file era
aaa bbb 444 555
ccc ddd 422 211
e tu fai la inserti di "xxx" allora
dopo hai un file con una riga che contiene solo xxx e quando poi
la vai a leggere .....
3) la tua insert permette di inserire solo stringhe lunghe max 4
  caratteri (il buffer della funzione insert e' dimensionato a 5
  caratteri!!!)
4) la tua funzione per calcolare la lunghezza in righe di un
file e' sbagliata concettualmente e praticamente: tra le cose
sbagliate: (i) l'ultima riga di un file potrebbe non essere terminata
da un '\n' e (ii) restituire come messaggio di errore un numero (1)
che potrebbe essere un output legittimo e' grave. (Cioe' se hai un file
con solo una riga viene interpretato come file non esistente. Dovevi far
restituire qualcosa come -1, ad esempio).
E in ogni caso da' risposte sbagliate:
per esempio il file che contiene:
aaa bbb 44 4\n
ccc ddd 3  1\n
viene visto come di lunghezza 3 ! e quindi poi quando
stampi vai a stampare linee inesistenti...
mentre lo stesso file senza l'ultimo '\n' viene
visto come inesistente...
Poi altre cose sparse:
a) Invochi 2 volte di seguito la funzione conta(). Va bene che questo 
programma e' un esercizietto, ma nella pratica, se tu avessi un file di
400 Mega non staresti a contare le righe 2 volte, ma memorizzeresti il
conto la prima volta...
b) nella funzione insert il buffer e' chiaramente sottodimensionato,
come ho gia' detto, e poi non capisco perche' lo vai ad azzerare ??
ora basta, perche' ho esaurito le mie forze...
ciao,
g.

Grazie tanto.
Ciao