fgets関数とwhileループ(feof関数の使い分け)

fgets(3)はwhileループの中でどう使えばいいのか、検証してみた。

以下、ソース全文。
whileの部分を変えてみる。

#include <stdio.h>
#include <string.h>

void testfunc(char *buf){
    printf("%s\n", buf);
} /* end of testfunc */

void main(int argc, char *argv[]){

    if(argc !=2){printf("argument error\n");return;}
    FILE *fp = fopen(argv[1], "r");

    char buf[16];
    char *p;
    /* test start ---> */
    while(!feof(fp)){
        fgets(buf, 16, fp);
        p = strchr(buf, '\n');
        if(p){*p = '\0';}

        testfunc(buf);        
    } /* end of while */
    /* <--- test end  */

    fclose(fp);
    
} /* end of main */

読ませるファイルは以下の2パターン。

test1.dat

A
BB
CCC[EOF]

test2.dat

A
BB
CCC
[EOF]

  • <パターン1> whileの条件式でfeof()を使う
    while(!feof(fp)){
        fgets(buf, 16, fp);
        p = strchr(buf, '\n');
        if(p){*p = '\0';}

        testfunc(buf);        
    } /* end of while */
test1.datを渡した結果

A
BB
CCC

test2.datを渡した結果

A
BB
CCC
CCC

4行目の出力は、bufに残っている内容を出力しているもの。

- <パターン2> feof()でbreakする

    while(1){
        fgets(buf, 16, fp);
        if(feof(fp)){break;}
        p = strchr(buf, '\n');
        if(p){*p = '\0';}

        testfunc(buf);        
    } /* end of while */
test1.datを渡した結果

A
BB

test2.datを渡した結果

A
BB
CCC

- <パターン3> whileの条件式でfgets()の返り値を使う

    while(fgets(buf, 16, fp)){
        p = strchr(buf, '\n');
        if(p){*p = '\0';}

        testfunc(buf);        
    } /* end of while */
test1.datを渡した結果

A
BB
CCC

test2.datを渡した結果

A
BB
CCC

こうしてみると、パターン3(fgets()の返り値をwhile文の条件式に使う)がいいのか。