C语言 使用 fgets 达到 EOF

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15484106/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:45:31  来源:igfitidea点击:

Reaching EOF with fgets

cunixeoffgets

提问by Fabio Carello

I'm writing a function that perform some authentications actions. I have a file with all the user_id:password:flagcouples structured like this:

我正在编写一个执行一些身份验证操作的函数。我有一个包含所有user_id:password:flag夫妻的文件,结构如下:

Users.txt

用户.txt

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

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

This is the code:

这是代码:

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 */

    }   
/*...*/    
}

How can I manage the EOF reaching? I saw that when EOF is reached fgetsdoesn't edits anymore the usr_psw_line but neither returns a NULL pointer. If EOF is reached it mean that no match are found in the users file and the loop breaks.

我如何管理 EOF 到达?我看到当达到 EOF 时fgets不再编辑 usr_psw_line 但也不返回 NULL 指针。如果达到 EOF,则意味着在用户文件中找不到匹配项并且循环中断。

Can someone give me some tips or suggests?

有人可以给我一些提示或建议吗?

回答by Keith Thompson

fgets()return a null pointer when it reaches end-of-file or an error condition.

fgets()当它到达文件结尾或错误条件时返回一个空指针。

(EOFis a macro that specifies the value returned by certain other functions in similar conditions; it's not just an abbreviation for the phrase "end of file".)

(EOF是一个宏,用于指定在类似条件下由某些其他函数返回的值;它不仅仅是短语“文件结尾”的缩写。)

You're ignoring the result returned by fgets(). Don't do that.

你忽略了返回的结果fgets()。不要那样做。

Note that just checking feof(fd)won't do what you want. feof()returns a true result if you've reached the end of the file. If you encounter an error instead, feof()still returns false, and you've got yourself an infinite loop if you're using feof()to decide when you're done. And it doesn't return true until afteryou've failed to read input.

请注意,仅检查feof(fd)不会执行您想要的操作。 feof()如果到达文件末尾,则返回 true 结果。如果您遇到错误,feof()仍然返回 false,并且如果您使用feof()来决定何时完成,那么您将陷入无限循环。直到您未能读取输入,它才会返回 true 。

Most C input functions return some special value to indicate that there's nothing more to read. For fgets()it's NULL, for fgetc()it's EOF, and so forth. If you like, you can call feof()and/or ferror()afterwards to determine whythere's nothing more to read.

大多数 C 输入函数会返回一些特殊值,以指示没有其他内容可读取。因为fgets()NULL,因为fgetc()EOF,等等。如果你愿意,你可以打电话feof()和/或ferror()事后确定为什么没有什么可阅读的了。

回答by Steve Valliere

You might want to try something like this in your loop:

你可能想在你的循环中尝试这样的事情:

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 */

}

With the extra code, the loop will terminate if fgetsreturns NULL (no more data to read) or if you're read the EOF mark or had any error on the file. I'm sure it is overkill, but those tests have always worked for me.

使用额外的代码,如果fgets返回 NULL(没有更多数据要读取),或者如果您读取 EOF 标记或文件有任何错误,则循环将终止。我敢肯定这是矫枉过正,但这些测试一直对我有用。