使用fscanf时无限循环

时间:2012-06-03 15:40:47

标签: c file infinite-loop

我用C编写了这个简单的程序,因为我现在正在大学学习FILES。我带了一个txt文件,其中包含最后一场比赛的结果列表,所以我的程序将按照我的要求显示格式化的数据。这是我的代码:

/* 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;


}

并且有我的txt文件:

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

当我运行我的程序时,它会返回第一个无限循环。为什么? 还有其他函数可以读取这些数据吗?

3 个答案:

答案 0 :(得分:3)

这个有效(从@Mahmoud Al-Qudsi借来;我不想要任何积分)

#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;
}

答案 1 :(得分:2)

您的问题是您没有进行任何错误检查。 EOF仅在文件末尾返回,但fscanf返回其匹配的参数数量,否则即使为0。

在您的代码中,fscanf仅在第一次匹配并读入变量,之后返回0。变量然后保留原始内容,并且您永远打印它。

如果您使用警告编译代码,则会发现您有多个问题:

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

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

如果您正在记录或检查fscanf的返回值,您会发现在每行末尾都没有检查\n。你的fprintf应该(可能)看起来更像这样:

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

答案 2 :(得分:2)

您需要在每次fscanf来电后吞下行尾字符 - 例如在while块的开头:

{
    fgetc(fp);
    ...
}

有关详细信息,请参阅此Microsoft KB article(该解释适用于任何C编译器)