4

私は今大学でファイルを勉強しているので、この簡単なプログラムをCで書きました。前回のレースの結果のリストを含む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はファイルの最後でのみ返されますが、fscanf0であっても、それ以外の場合に一致した引数の数を返します。

コードで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チェックしていないことに気付くでしょう。\nfprintfは(おそらく)次のようになります。

while (fscanf (fp, "%d %d %d %s %s %s %s %.2f\n",
于 2012-06-03T15:53:52.890 に答える
2

fscanfすべての呼び出しの後で、たとえばwhileブロックの先頭で、行末文字を飲み込む必要があります。

{
    fgetc(fp);
    ...
}

詳細については、このMicrosoft KBの記事を参照してください(説明はすべての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 に答える