4

我用 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

当我运行我的程序时,它返回给我第一个的无限循环。为什么?是否有其他功能可以读取这些数据?

4

3 回答 3

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",
于 2012-06-03T15:53:52.890 回答
2

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

{
    fgetc(fp);
    ...
}

有关更多详细信息,请参阅此Microsoft 知识库文章(解释适用于任何 C 编译器)

于 2012-06-03T15:55:34.377 回答
2

这个有效(借自@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;
}
于 2012-06-03T16:32:00.470 回答