如何正确利用fgets()和strncmp()函数?

时间:2019-06-16 13:55:56

标签: c

我正在尝试通过利用fgets()和strncmp()函数保护一些C代码。该程序运行良好,但是,如果我多次输入正确的密码(“ password”),它仍会指示正确的密码。同样,即使使用fgets(),结果(如果长于缓冲区中指示的9)也将出现在输出中。任何帮助将不胜感激。

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

int main(void)
{
    char buffer[9];
    int pass = 0;
    char password[] = "password";

    printf("\n Enter your password : \n");
    fgets(buffer, 9, stdin);

    if(strcmp(buffer, password))
    {
        printf ("\n Incorrect Password \n");
    }
    else
    {
        printf ("\n Correct Password \n");
        pass = 1;
    }

    if(pass)
    {
        printf ("\n Root privileges authorized \n");
    }

    return 0;
}

2 个答案:

答案 0 :(得分:1)

您的代码的问题是fgets会将输入中的前8个字符删除,而忽略其余的字符。显然,如果您邀请密码,则您不想忽略任何输入!您可能想要做更多的事情,以确保捕获全部输入。

我的前两个尝试回答这个问题是错误的。感谢wildplasser扶住我的脚。

因此,hack的答案是:使用很大的缓冲区。 fgets可能是您更轻松的解决方案。

或者,您可以在输入字符串超出缓冲区时动态分配内存。

但是,只是为了好玩,这里有一个实现使我们脱离了我不知道getchar所在的“行缓冲区”陷阱。

为此,我在这里利用了一个非常漂亮的评论:getchar() and stdin

PS:好的,好的,我这次进行了测试。有用。在我的Mac上。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>

int main(void)
{
    int c, i;
    char buffer[9];
    struct termios tty_opts_default, tty_opts_raw;

    if (!isatty(STDIN_FILENO)) {
      printf("Error: stdin is not a TTY\n");
      return 1;
    }

    /* save tty settings for later. */
    tcgetattr(STDIN_FILENO, &tty_opts_default);

    /* put tty settings into raw mode. */
    cfmakeraw(&tty_opts_raw);
    tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_raw);

    /* NOW we can grab the input one character at a time. */
    c = getchar();
    while (i < 8 && c != EOF && c != '\n' && c != '\r') {
      /* Since we are collecting a pwd, we might want to enforce other
         password logic here, such as no control characters! */
      putchar('*');
      buffer[i++] = c;
      c = getchar();
    }
    buffer[i] = '\0';

    /* Restore default TTY settings */
    tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_default);

    /* Report results to user. */
    printf("\nPassword received.\n");
    printf("(It was '%s' -- don't tell anyone! Quick! Hide the terminal!)\n", buffer);

    return 0;
}

答案 1 :(得分:0)

  • fgets()也会读取(CR +)LF,并将其存储到缓冲区中。
  • 但是,如果有足够的地方!
  • 否则,您的缓冲区将包含前n-1个字符以及一个NUL字符。

    因此:分配一个足够大的缓冲区,然后剥离CR / LF:


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

int main(void)
{
    int pass = 0;
    char password[] = "password";
    char buffer[3+ sizeof password];

    printf("\n Enter your password : \n");
    fgets(buffer, sizeof buffer, stdin);
    buffer[strcspn(buffer,"\r\n")]=0;

    if(strcmp(buffer, password))
    {
        printf ("\n Incorrect Password \n");
    }

    else
    {
        printf ("\n Correct Password \n");
        pass = 1;
    }

    if(pass)
    {
        printf ("\n Root privileges authorized \n");
    }

    return 0;
}