Достижение 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 достигнут, это означает, что совпадение не найдено в файле пользователя, и цикл прерывается.

Может кто-нибудь дать мне несколько советов или предложений?

Ответ 1

fgets() возвращает нулевой указатель, когда он достигает конца файла или условия ошибки.

(EOF) - макрос, который задает значение, возвращаемое некоторыми другими функциями в аналогичных условиях, а не только аббревиатуру фразы "конец файла".)

Вы игнорируете результат, возвращаемый fgets(). Не делайте этого.

Обратите внимание, что просто проверка feof(fd) не будет делать то, что вы хотите. feof() возвращает истинный результат, если вы достигли конца файла. Если вы столкнулись с ошибкой, feof() все еще возвращает false, и у вас есть бесконечный цикл, если вы используете feof(), чтобы решить, когда вы закончите. И он не возвращает true до тех пор, пока вы не прочитаете ввод.

Большинство функций ввода C возвращают некоторое специальное значение, чтобы указать, что читать больше нечего. Для fgets() it NULL, для fgetc() it EOF и т.д. Если хотите, вы можете позвонить feof() и/или ferror() впоследствии, чтобы определить, почему читать больше нечего.

Ответ 2

Возможно, вы захотите попробовать что-то подобное в своем цикле:

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 или имели какую-либо ошибку в файле. Я уверен, что это слишком много, но эти тесты всегда работали для меня.