web-dev-qa-db-ja.com

到達EOF fgetsで

いくつかの認証アクションを実行する関数を書いています。すべてのuser_id:password:flagカップルは次のように構成されています:

Users.txt

user_123:a1b2:0 user_124:a2b1:1 user_125:a2b2:2

これはコードです:

int main(){
    /*...*/

    /*user_id, password retrieving*/
    USRPSW* p = malloc(sizeof(USRPSW));
    if(p == NULL){
        fprintf(stderr, "Dynamic alloc error\n");
        exit(EXIT_FAILURE);
    }
    memset((void*)p, 0, sizeof(USRPSW));

    if(usr_psw_read(acc_sock_ds, p->user_id, USR_SIZE) <= 0){
        printf("Failed read: connection with %s aborted.\n",
                 inet_ntoa(client_addr.sin_addr));
        close(acc_sock_ds);
        continue;
    }

    if(usr_psw_read(acc_sock_ds, p->password, PSW_SIZE) <= 0){
        printf("Failed read: connection with %s aborted.\n",
                 inet_ntoa(client_addr.sin_addr));
        close(acc_sock_ds);
        continue;
    }

    /*Authentication through user_id, password*/
    FILE *fd;
    fd = fopen(USERSFILE, "r");
    if(fd == NULL){
        fprintf(stderr, "Users file opening error\n");
        exit(EXIT_FAILURE);
    }

    char *usr_psw_line = malloc(USR_SIZE+PSW_SIZE+3+1);
    if(usr_psw_line == NULL){
        fprintf(stderr, "Dynamic alloc error\n");
        exit(EXIT_FAILURE);
    }

    while(1){

        memset((void*)usr_psw_line, 0, sizeof(USR_SIZE+PSW_SIZE+3+1));
        fgets(usr_psw_line, USR_SIZE+PSW_SIZE+3+1, fd);
        printf("%s\n", usr_psw_line);
        fseek(fd, 1, SEEK_CUR);


        /*EOF management*/
        /*usr_id - password matching checking */

    }   
/*...*/    
}

EOF到達を管理するにはどうすればよいですか?EOFに到達すると、fgetsはusr_psw_lineを編集しなくなりますが、 NULLポインターEOFに達した場合、ユーザーファイルで一致が見つからず、ループが中断します。

誰かが私にいくつかのヒントや提案を与えることはできますか?

11
Fabio Carello

fgets()は、ファイルの終わりまたはエラー状態に達すると、nullポインターを返します。

EOFは、同様の条件で他の特定の関数によって返される値を指定するマクロです。これは、「ファイルの終わり」というフレーズの単なる省略形ではありません。)

fgets()によって返された結果を無視しています。それをしないでください。

feof(fd)をチェックするだけでは、期待どおりに動作しないことに注意してください。 feof()は、ファイルの終わりに達した場合にtrueの結果を返します。代わりにエラーが発生した場合でも、feof()はfalseを返します。feof()を使用して終了を決定すると、無限ループになります。そして、それはafterが入力の読み取りに失敗するまでtrueを返しません。

ほとんどのC入力関数は、特別な値を返し、これ以上読む必要がないことを示します。 fgets()の場合はNULLfgetc()の場合はEOFなどです。必要に応じて、後でfeof()ferror()を呼び出して、whyを判断できます。これ以上読む必要はありません。

21
Keith Thompson

あなたはあなたのループでこのようなものを試してみたいかもしれません:

while(1)
{
    memset((void*)usr_psw_line, 0, sizeof(USR_SIZE+PSW_SIZE+3+1));
    if( !fgets(usr_psw_line, USR_SIZE+PSW_SIZE+3+1, fd)
     || ferror( fd ) || feof( fd ) )
    {
        break;
    }
    printf("%s\n", usr_psw_line);
    fseek(fd, 1, SEEK_CUR);

    /*EOF management*/
    /*usr_id - password matching checking */

}

余分なコードにより、fgetsがNULL(これ以上読み取るデータがない)を返した場合、またはEOFマークが付いているか、ファイルにエラーがあった場合は、ループが終了します。 。やり過ぎだと私は確信していますが、これらのテストは常に私にとってはうまくいきました。

3
Steve Valliere