Newsgroup: it.comp.lang.c
Titolo: Leggere float da file di testo

ciao NG,
ho un file di testo del tipo
1.2
0.45
3
4.567
....
c'è un modo diretto per leggere il valore dal file e memorizzarlo
in una variabile di tipo float??
ciao
tommaso

in una variabile di tipo float??
fgets + atof ?
fgets + scanf ?
fscanf ?
Non hai che l'imbarazzo della scelta.
ciao
bp

 fscanf ?
se leggo
    fscanf(FILE, "%f", f_variabile);
    printf("%f", f_variabile);
stampa na schifezza!!
ciao

     printf("%f", f_variabile);
Qui i newline rimangono nel buffer.  Controlla la FAQ.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it


ciao a te
bp
/*********** esempio *************/
/* il programma vuole come parametro il nome del file */
#include <stdlib.h>
#include <stdio.h>
#define BUFSIZE 100  // qui metti la dim. che ti fa + comodo
main(int argc, char *argv[])
{
 char s[BUFSIZE];
 FILE *file;
 double f;
 int l;
 if (argc != 2)
  return 1;
 if ((file = fopen(argv[1], "r")) == NULL)
  return 2;
 while(!feof(file))
 {
  if (fgets(s, BUFSIZE, file) != NULL)
  {
   // bisogna mettere anche il controllo per
   // vedere se BUFSIZE e' troppo piccolo...
   // strip del newline (fgets legge anche quello)
   l = strlen(s);
   if (l > 0)
    if (s[l-1] == '\n')
     s[l-1] = '\0';
   // soluzione fgets + atof
   f = atof(s);
   printf("stringa = (%s)   double = %f\n", s, f);
   // soluzione fgets + atof (la fscanf e' del tutto analoga)
   sscanf(s, "%f", &f);
   printf("stringa = (%s)   double = %f\n", s, f);
  }
 }

Scusate, un cut&paste troppo veloce, al programma manca la fclose e
l'ultima }.
Ecco il prg completo.
#include <stdlib.h>
#include <stdio.h>
#define BUFSIZE 100  // qui metti la dim. che ti fa + comodo
main(int argc, char *argv[])
{
 char s[BUFSIZE];
 FILE *file;
 double f;
 int l;
 if (argc != 2)
  return 1;
 if ((file = fopen(argv[1], "r")) == NULL)
  return 2;
 while(!feof(file))
 {
  if (fgets(s, BUFSIZE, file) != NULL)
  {
   // bisogna mettere anche il controllo per
   // vedere se BUFSIZE e' troppo piccolo...
   // strip del newline (fgets legge anche quello)
   l = strlen(s);
   if (l > 0)
    if (s[l-1] == '\n')
     s[l-1] = '\0';
   f = atof(s);
   printf("stringa = (%s)   double = %f\n", s, f);
   sscanf(s, "%f", &f);
   printf("stringa = (%s)   double = %f\n", s, f);
  }
 }
 fclose(file);
 return 0;
}

  {
questo e' sbagliato, e viene letta una linea di troppo.  e' lasciato
come compito a casa al lettore il capire perche'.


Che il programma sia perfettibile, non ci piove. Del resto, e' solo un
esempio.
Comunque, funziona, e *non* legge nessuna riga di troppo.
Empiricamente, ovvero provandolo, se il file ha 3 righe, ne legge 3, se non
ne ha,
non ne legge, se ne ha 1, ne legge 1 eccetera.
Dato che il prg funziona, lascio a Maurizio capire perche' ;-)
Suggerimento, dall'help in linea della fgets
Each of these functions returns string. NULL is returned to indicate an
error or an end-of-file condition.
Use feof or ferror to determine whether an error occurred
E' comunque vero che nel prg il controllo non c'e'... ma come ho detto prima
che ip prg e' perfettibile.
ciao
bp
Maurizio Loreti wrote in message ...


 Comunque, funziona, e *non* legge nessuna riga di troppo.
Non e' vero.  Ecco il solito esempio:
MLO@mlinux 36 $ cat file.txt
1.2
0.45
3
4.567
MLO@mlinux 37 $ cat foo.c
#include <stdio.h>
#include <stdlib.h>
#define LONG_ENOUGH 128
int main() {
  FILE *fp = fopen("file.txt", "r");
  if (fp) {
    char buffer[LONG_ENOUGH];
    while (!feof(fp)) {
      fgets(buffer, LONG_ENOUGH, fp);
      printf("%s", buffer);
    }
    fclose(fp);
  }
  return 0;
}
MLO@mlinux 38 $ gcc -ansi -pedantic -Wall -o foo foo.c
MLO@mlinux 39 $ ./foo
1.2
0.45
3
4.567
4.567
MLO@mlinux 40 $
(Notare l'ultime linea ripetuta due volte).  Odio quando la gente nega
l'evidenza; e se il tuo compilatore non si comporta in questo modo,
ebbene, non e' standard.
Il motivo e' che l'indicatore di end-of-file per lo stream viene
settato *DOPO* che la fine del file e' stata raggiunta, e non prima
della lettura destinata a fallire; ed il buffer non viene aggiornato.
Coloro che non conoscono il C ma vengono dal Pascal tendono a
commettere questo errore di prammatica.  In C invece si fa cosi':
  while (fgets(...)) {
    /* processa la linea */
  }
  /* qui all'end-of-file o in caso di errore */
  if (ferror(fp)) {
    perror(...); /* avvisa l'utente della natura dell'errore */
  }
  if (fclose(fp)) {
    perror(...);


--
Decisamente il tuo e' un codice piu' elegante e leggibile del mio, ma questo
non toglie che pure il mio prg (con la modifica per testare ferror) faccia
esattamente le stesse cose (ok ok, a fare i pignoli non testo la fclose). Se
poi mi dici che e' brutto, mica mi offendo, anche perche' e' la verita'.
Pero' funziona.
Ciao
bp
P.S.: chiedo scusa al NG per il post forse un po' lungo...

 Comunque, funziona, e *non* legge nessuna riga di troppo.
Per essere precisi, fa una fgets() di troppo. 8)
Non c'è ragione di non usare fgets() subito, ad es.:
       while (fgets(s, sizeof s, file)) {
              /* fai quel che devi */
       }
       if (ferror(file)) {
              /* errore */
       }
Ciao ciao,
Andrea
-- 
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and 
 the Ugly)."
(by Matt Welsh)

       }
Comunque anche questa fa una fgets in piu' rispetto al numero di righe del
file, altrimenti come fai ad uscire dal ciclo while?
ciao
bp

   if (fgets(s, BUFSIZE, file) != NULL)    // **** NOTARE CHE C'E' L'IF ****
Scusami - dovro' farmi visitare dall'oculista.  Veramente spiacente!


 Ne fa una in piu' rispetto al numero di righe del file, ma non e' di troppo:
Ops...intendevo che di troppo è la feof() ! 8)
E' inutile testare la condizione di uscita in quel modo, quando
ti basta usare la sola fgets().
