用于登录验证的循环中的fgets

时间:2018-06-12 11:55:26

标签: c

我在c中有这个登录程序,它为用户提供最多3次登录尝试。 我使用fgets来避免缓冲区溢出,但是当我输入超过16个字符时会发生这种情况:

  

Enterlogin:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa   输入密码:输入登录名:输入密码:输入登录名:输入   密码:无效的登录名和/或密码

而不是仅读取前16'a'。 这是我的代码:

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


int checkpasswd();

int main() {

    int result;

    result = checkpasswd();

    if (result == 1)
        printf("Password correct - Login approved\n");
    else
        printf("Invalid login and/or password\n");

    return 0;
}

int checkpasswd(void) {

    char name[16], passwd[16];
    int correct = 0, attempts = 0;

    while ((attempts != 3)&&(correct == 0)) {
        printf("Enter login:");
        fgets(name, sizeof(name), stdin);
        printf("Enter password:");
        fgets(passwd, sizeof(passwd), stdin);

        if ((strncmp(name, "admin", strlen(name) - 1) == 0) && (strncmp(passwd, "secret", strlen(passwd) - 1) == 0))
            correct = 1;
        else
            attempts++;
    }

    if (correct)
        return 1;
    else return 0;
}

1 个答案:

答案 0 :(得分:3)

首先,您应该检查fgets返回的内容。如果失败,它将返回NULL

至于你的问题,fgets函数不一定会读整行。如果您告诉fgets最多读取16个字符(包括终结符),那么fgets将从输入中读取最多15个字符,然后将其余字符留在缓冲区中。它将在换行前读取并丢弃不适合缓冲区的内容。

要验证您获得fgets的整行,请检查字符串中的最后一个字符是换行符。

为了帮助您,您需要执行类似

的操作
if (fgets(name, sizeof name, stdin) == NULL)
{
    // Error or end-of-file, either way no use in continuing
    break;
}

if (strcspn(name, "\n") == strlen(name))
{
    // No newline in string, there might be more to read in the input buffer
    // Lets read and discard all remaining input in the input buffer until a newline
    int c;
    while ((c = fgetc(stdin)) != EOF && c != '\n')
    {
    }

    // TODO: Should probably tell the user about this event

    // Continue with next attempt
    ++attempts;
    continue;
}

我建议您将其分解为一个单独的函数,您也可以重复使用它来读取密码。