LoginSignup
2
2

More than 5 years have passed since last update.

データがないのにfscanfで読み続けるとどうなるか

Last updated at Posted at 2015-11-21

概要

fscanfでファイルからデータを読む場面がある。
一般にどのくらいあるかは分からないがC言語の初学者は多いのではないだろうか。

さて、テキストデータを読むとしてデータ以上に読み込もうとしたらどうなるだろうか。
初学者であれば実行して確認して欲しいが、念のため私の環境下で結果も示す。

ソースコードを見る。

以下に実行するソースコードとファイルの中身を示す。

test1.cpp
#include <stdio.h>

int main()
{
    FILE *fp;
    int tmp;

    if((fp=fopen("test1.txt","r"))==NULL)
    {
        printf("無。\n");
        return 0;
    }

    for(int i=0;i<10;i++)
    {
        fscanf(fp,"%d",&tmp);
        printf("%d\n",tmp);
    }

    fclose(fp);
    return 0;
}
test1.txt
1
2
3
4
5

動作確認

実行すると以下の結果を得られた。

1
2
3
4
5
5
5
5
5
5

どうやら取得できないとバッファが出てしまうようだ。

修正方法は?

対処としては、scanf/fscanfの戻り値として、うまく代入できた個数、または、変換失敗でEOF(-1)が返ってくる。戻り値をチェックして、妥当な値が入ってるか、確認するとよいね。
例) int ret = fscanf(fp, "%d %d", &n1, &n2);
に対し、
1 2 を入力 => ret = 2
1 a を入力 => ret = 1
...

@mt08さんよりコメントを頂いたので実際にやってみる。

成功/失敗を見分ける例として以下のように書き変えた。

test2.cpp
#include <stdio.h>

int main()
{
    FILE *fp;
    int tmp,ret;


    if((fp=fopen("test1.txt","r"))==NULL)
    {
        printf("無。\n");
        return 0;
    }

    for(int i=0;i<10;i++)
    {
        ret=0;
        ret=fscanf(fp,"%d",&tmp);
        printf("%d %d\n",tmp,ret);
    }

    fclose(fp);
    return 0;
}

結果は以下のとおり

1 1
2 1
3 1
4 1
5 1
5 -1
5 -1
5 -1
5 -1
5 -1

成功している部分では1,失敗している部分では-1を返していたことが確認できた。

次のデータの時はどうか

test2.txt
1 6
2 a
3 7
4 8
5 9
test3.cpp
#include <stdio.h>

int main()
{
    FILE *fp;
    int tmp[2],ret;


    if((fp=fopen("test2.txt","r"))==NULL)
    {
        printf("無。\n");
        return 0;
    }

    for(int i=0;i<10;i++)
    {
        ret=0;
        ret=fscanf(fp,"%d %d",&tmp[0],&tmp[1]);
        printf("%d %d %d\n",tmp[0],tmp[1],ret);
    }

    fclose(fp);
    return 0;
}
1 6 2
2 6 1
2 6 0
2 6 0
2 6 0
2 6 0
2 6 0
2 6 0
2 6 0
2 6 0

確かに2つの値が成功しているときは2,片方の時は1が出ている。
その後は文字を入れてしまったため処理が停止してるように見える。
事実データは入力ストリーム上に残ってしまっている。

そういった場合の事例はWikipediaに載っていたのでこちらも参照されたい。
https://ja.wikipedia.org/wiki/Scanf#.E7.95.B0.E5.B8.B8.E3.81.AA.E5.85.A5.E5.8A.9B.E3.81.8C.E8.A1.8C.E3.82.8F.E3.82.8C.E3.81.9F.E6.99.82.E3.81.AE.E5.87.A6.E7.90.86

2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2