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