简体   繁体   中英

Infinite loop when using fscanf

I wrote this simple program in C, because I'm studying FILES right now at University. I take a txt file with a list of the results of the last race so my program will show the data formatted as I want. Here's my code:

/* Esercizio file Motogp */
#include <stdio.h>
#define SIZE 20

int main ()
{
    int pos, punt, num;
    float kmh;
    char nome[SIZE+1], cognome[SIZE+1], moto[SIZE+1];
    char naz[SIZE+1], nome_file[SIZE+1];

    FILE *fp;

    printf ("Inserisci il nome del file da aprire: ");
    gets (nome_file);

    fp = fopen (nome_file, "r");

    if (fopen == NULL)
        printf ("Errore nell' apertura del file %s\n", nome_file);
    else {

        while (fscanf (fp, "%d %d %d %s %s %s %s %.2f",
                &pos, &punt, &num, nome, cognome, naz, moto, &kmh) != EOF ) {

              printf ("Posizione di arrivo: %d\n", pos);
              printf ("Punteggio: %d\n", punt);
              printf ("Numero pilota: %d\n", num);
              printf ("Nome pilota: %s\n", nome);
              printf ("Cognome pilota: %s\n", cognome);
              printf ("Nazione: %s\n", naz);
              printf ("Moto: %s\n", moto);
              printf ("Media Kmh: %d\n\n", kmh);
        }
    }

    fclose(fp);

    return 0;
}

and there's my txt file:

1   25  99  Jorge LORENZO    SPA    Yamaha  164.4   
2   20  26  Dani PEDROSA     SPA    Honda   164.1   
3   16  4   Andrea DOVIZIOSO ITA    Yamaha  163.8   
4   13  1   Casey STONER     AUS    Honda   163.8   
5   11  35  Cal CRUTCHLOW    GBR    Yamaha  163.6   
6   10  19  Alvaro BAUTISTA  SPA    Honda   163.5   
7   9   46  Valentino ROSSI  ITA    Ducati  163.3   
8   8   6   Stefan BRADL     GER    Honda   162.9   
9   7   69  Nicky HAYDEN     USA    Ducati  162.5   
10  6   11  Ben SPIES    USA    Yamaha  162.3   
11  5   8   Hector BARBERA   SPA    Ducati  162.1   
12  4   17  Karel ABRAHAM    CZE    Ducati  160.9   
13  3   41  Aleix ESPARGARO  SPA    ART 160.2   
14  2   51  Michele PIRRO    ITA    FTR 160.1   
15  1   14  Randy DE PUNIET  FRA    ART 160.0   
16  0   77  James ELLISON    GBR    ART 159.9   
17  0   54  Mattia PASINI    ITA    ART 159.4   
18  0   68  Yonny HERNANDEZ  COL    BQR 159.4   
19  0   9   Danilo PETRUCCI  ITA    Ioda    158.2   
20  0   22  Ivan SILVA   SPA    BQR 158.2

When I run my program, it return me an infinite loop of the first one. Why? Is there another function to read those data?

This one works (borrowed from @Mahmoud Al-Qudsi; I don't want any points for this)

#include <stdio.h>
#define SIZE 20

int main (int argc, char **argv)
{
    int pos, punt, num;
    float kmh;
    char nome[SIZE+1], cognome[SIZE+1], moto[SIZE+1];
    char naz[SIZE+1];

    FILE *fp;

    fp = fopen (argv[1], "r");

    if (!fp ) { printf ("Errore nell' apertura del file %s\n", argv[1]); return 0; }

        while (fscanf (fp, "%d %d %d %s %s %s %s %f\n",
                &pos, &punt, &num, nome, cognome, naz, moto, &kmh) == 8 ) {

              printf ("Posizione di arrivo: %d\n", pos);
              printf ("Punteggio: %d\n", punt);
              printf ("Numero pilota: %d\n", num);
              printf ("Nome pilota: %s\n", nome);
              printf ("Cognome pilota: %s\n", cognome);
              printf ("Nazione: %s\n", naz);
              printf ("Moto: %s\n", moto);
              printf ("Media Kmh: %f\n\n", kmh);
        }

    fclose(fp);

    return 0;
}

Your problem is that you are not doing any error checking. EOF is only returned at the end of file, but fscanf returns the number of arguments it matched otherwise, even if 0.

In your code, fscanf matches and reads into the variables just the first time, returning 0 thereafter. The variables then retain the original content, and you print it forever anon.

If you compiled your code with warnings, you'd see you have multiple issues:

test.c:23:51: warning: invalid conversion specifier '.'
      [-Wformat-invalid-specifier]
        while (fscanf (fp, "%d %d %d %s %s %s %s %.2f",
                                                ~~^

and

test.c:33:36: warning: conversion specifies type 'int' but the argument has type
      'double' [-Wformat]
              printf ("Media Kmh: %d\n\n", kmh);
                                  ~^       ~~~
                                  %f

And if you were logging or checking the return value of fscanf , you'd realize that you're not checking for \\n at the end of each line. Your fprintf should (possibly) look more like this:

while (fscanf (fp, "%d %d %d %s %s %s %s %.2f\n",

You need to swallow the end-of-line character after every fscanf call -- eg at the beginning of the while block:

{
    fgetc(fp);
    ...
}

see this Microsoft KB article for more details (the explanation applies to any C compiler)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM