2016-09-13 18 views
1

今後の課題を練習する中で、fscanfを使用して問題に遭遇し、不正な形式がプログラムに入力されたときに通知を出しています。私はfscanfの戻り値を使用しなければならないと確信していますが、whileループの中でどのように使用するのか分かりません。現在、プログラムは "a3"のような値が入力されたときに連続的にループしますが、数字3を2回出力する点を除いて、 "3e"はほとんどうまく動作します。fscanfの使用:入力内の文字の検索

ワーキングのscanfコード:

int intGet(int min, int max) { 

int input = 0; 
char temp = ' '; 
printf("Enter a number in between [%d-%d]: ", min, max); 

if (scanf("%d%c", &input, &temp) != 2){ 
    errorNo = 1; 
    return EXIT_FAILURE; 
} 
if (temp != '\n'){ 
    errorNo = 2; 
    return EXIT_FAILURE; 
} 
if (input < min || input > max){ 
    errorNo = 3; 
    return EXIT_FAILURE; 
} 
else { 
    printf("Read %d\n", input); 
} 
return EXIT_SUCCESS; 

連続ループと同じ考え方に沿って、関数fscanfコード:

int intGet(int min, int max) { 
int counterValid = 0; 
int counterInvalid = 0; 
int entry = 0; 
int total = 0; 
int input = 0; 
int check = 0; 
char temp = ' '; 
FILE *fp; 

fp = fopen("02_num.txt", "r"); 
if (!fp) 
{ 
    perror("fopen()"); 
    exit(EXIT_FAILURE); 
} 
printf("----------------------------------------------------------\n"); 
printf("Entry\tInvalid\tValid\tNumber\n"); 
printf("----------------------------------------------------------\n"); 

fscanf(fp, "%*[^\n]\n"); //skips first line (min and max) 


    while (check != EOF){ 

check = fscanf(fp, "%d%c", &input, &temp); 

    if (check == EOF){ 
     exit(EXIT_SUCCESS); 
    } 
    if (check != 2){ 
     counterInvalid += 1; 
     entry += 1; 
     printf("%d\t*\t\t%d\tIncorrect Format\n", entry, input); 
    } 
    if (temp != '\n'){ 
     counterInvalid += 1; 
     entry += 1; 
     printf("%d\t*\t\t%d\tExtra Characters\n", entry, input); 
    } 
    if (input < min || input > max){ 
     counterInvalid += 1; 
     entry += 1; 
     printf("%d\t*\t\t%d\tInput Number out of Range\n", entry, input); 
    } 
    else{ 
     counterValid += 1; 
     entry +=1; 
     total += input; 
     printf("%d\t\t*\t%d\n", entry, input); 
    } 
} 
    printf("----------------------------------------------------------\n"); 
entry +=1; 
printf("%d\t%d\t%d\t%d\n", entry, counterInvalid, counterValid, total); 
return EXIT_SUCCESS; 
} 

このコード出力このようになりますテーブルを、その後は以下となります。

***************************************************** 
     Entry Invalid Valid Number 
     1   *     32 
***************************************************** 
// adds invalid and valid entry totals, displays then here, adds totals of valid numbers and also outputs them here. 

このコードで使用されていた02_num.txtファイルの最初の2つの数値は、最小値と最大値です、別の関数を読んでください。

1 15 //min and max 
23 
45 
67 
8990 
3e 
12 
a3 

物事は私はで動作するようにしようとした場合whileループ/:

while (check != EOF){ 

check = fscanf(fp, "%d%c", &input, &temp); 
    if (check != 2){ 
     counterInvalid += 1; 
     entry += 1; 
     printf("%d\t*\t\t%d\tIncorrect Format\n", entry, input); 
    } 

リターンをチェック:

が(現在は最も近い)関数fscanfの戻り値を記録するための変数を定義しますまた、if文の値も変更します(ファイルを2回スキャンして正しく出力しません)。

私は行方不明になっている情報があれば教えてください、私はちょっとここにこだわっています。おそらくちょうど愚かな間違い私は行方不明だが、事前に感謝!

+0

まず、全体の行を読みたい場合はどうすればよいでしょうか。 'scanf'ではなく' fgets'ですか?第2に、ほとんどの 'scanf'フォーマット指定子(例えばすべての数値フォーマット)は、先頭の空白を読み込んで破棄します。 –

+0

'a3'が読み込まれると'%d'は 'a'で失敗し、' a'で次の試行は失敗し、次は 'a'で失敗します。 '%e'が' e'を読み込み、次の繰り返しで '%d'が空白(改行)をスキップするので、' 3e'の場合は機能します。行ベースの入力に 'scanf()'などを使用しないでください。それはラインの境界を気にしません。代わりに 'fgets()'(または 'getline()')と 'sscanf()'を使います。 –

+0

@JoachimPileborg私はfgetsがうまくいくことは知っていますが、目的はもっと基本的なI/Oの形に慣れることです。私はこのケースではfscanfに限定されています – Sentience

答えて

3

ループの問題は、fscanfがゼロを返すときに行うことです。とりわけ、fscanfを同じ書式文字列で再度呼び出すと、結果がゼロになることを意味します。なぜなら、最初にゼロになる入力の問題が解決されていないからです。

あなたは fscanfからゼロバックを取得するときにラインをスキップするコードを追加する必要があり

- 例えば、あなたのfscanf(fp, "%*[^\n]"); fscanf(fp, "%*1[\n]");は、Jonathan Lefflerchuxによって修正され、動作します。

+0

書式文字列の末尾にある '\ n'(または後続の空白)は、空白でないものを見つけるまで、空白(改行を含む)を読み込むことに注意してください。入力がインタラクティブなのは悲しいことです。 '%* [\ n]'を使う方が良いでしょう。これは、1つの改行を割り当てられていない読み込みです。唯一の問題は、 '%* [\ n]'が実際に一致しているかどうかを知ることができないということです。戻り値にカウントされません。 –

+0

これはすばらしく働いてくれた: – Sentience

+0

(私は "面白い(特有の)"コメントを取り除いた - scanf ()は空の行で失敗しました。空行で%* 1 [\ n] "'%の最初の変換指定を満たす文字はありません。私の考えではバグを修正するよりも、o/sのバグを修正することをお勧めします)これはあまりにも早く過ぎるはずです –

関連する問題