strcmp返回错误的值

时间:2019-02-14 12:51:46

标签: c strcmp

有人可以解释一下为什么strcmp即使密码正确/错误也返回相同的值吗?我在include部分的下面定义了有效的密码,并在程序结尾处输入了一个密码来进行检查。

这是我的代码:

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

#define TIME 10
#define MAXPASSWORD 12
#define PASSWORD "pass123"

void sigalrm_handler() {
    printf("\nERR: Time is up...\n");
}

int getch() {
    struct termios oldtc, newtc;
    int ch;
    tcgetattr(STDIN_FILENO, &oldtc);
    newtc = oldtc;
    newtc.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newtc);
    ch=getchar();
    tcsetattr(STDIN_FILENO, TCSANOW, &oldtc);
    return ch;
}

int main(int argc, char * argv[]) {
    char password[MAXPASSWORD] = {0};
    printf("Enter correct password. You have %d seconds: ", TIME);
    signal(SIGALRM, sigalrm_handler);
    alarm(TIME);
    fflush(stdout);

    for(int i=0; i<MAXPASSWORD; i++)
    {
      password[i] = getch();
      if (password[i] == '\n')
        break;
      printf("*");
    }

    if (strcmp(password, PASSWORD) == 0) {
        printf("\nValid password\n");
    } else {
        printf("\nInvalid password\n");
    }
}

3 个答案:

答案 0 :(得分:3)

您忘了用NUL代替\n

...
for(int i=0; i<MAXPASSWORD; i++)
{
  password[i] = getch();
  if (password[i] == '\n')
  {
    password[i] = 0;   // <<<< add this line
    break;
  }
  printf("*");
}
...

还有另一个问题:请考虑如果用户在按下 Enter 之前输入了11个以上的字符,该怎么办。我让你发现自己是一种锻炼。

答案 1 :(得分:3)

问题是您将\n存储在输入缓冲区中,因此pass123pass123\n将不匹配。

如果您发现null,则\n将终止输入。

  if (password[i] == '\n')
  {
     password[i] = '\0';
     break;
  }

答案 2 :(得分:1)

您已经声明strcmp()表示两个字符串是相等的,当您知道它们不是...

其他答案中提到的\n的问题仍然存在,如果您确实看到strcmp()返回错误的指示,问题就变成了为什么?

在C中,string被定义为null终止的字符数组。因此,例如,如果您具有以下条件:

char password[MAXPASSWORD] = {0};//where MAXPASSWORD == 12

|p|a|s|s|1|2|3|\0|\0|\0|\0|\0| // `PASSWORD ` - legal string
|s|o|m|e|p|a|s|s|1|2|3|4|\n|  // 'password' 

即使替换了\n字符,该数组也太长了一个字符:

|s|o|m|e|p|a|s|s|1|2|3|4|\0|  // 'password' - too long by 1 character
                        ^     // end of legal definition of `password`

如果password数组中的字符过多,即使在这种情况下,在合法定义之外的 位置将最后一个char \n用NULL替换后,字符串中的代码将受 undefined behavior 的约束。

字符串函数专门用于strings。当显示一个非空终止的字符数组时,该函数(在本例中为strcmp(),因为它正在寻找nul终止符以知道字符串的末尾在哪里),不能期望它起作用具有可预测性。 (在这种情况下,nul字符的位置将导致未定义行为。)

为防止这种情况发生,即使用户能够在password中输入太多字符,也始终以以下语句结束:

password[MAXPASSWORD-1] = 0;  //for a properly initialized array, (as your code indicates)
                              //this guarantees termination occurs 
                              //within legal memory area of defined variable. 

这样,将不会有未定义的行为,并且如果字符串不同,strcmp()将会表明。