strcmp returns 错误值

strcmp returns wrong value

谁能解释一下为什么 strcmp returns 即使密码是 correct/incorrect 也是一样的值?我在包含部分下面定义了有效密码,并在我的程序结束时用输入的密码检查它。

这是我的代码:

#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");
    }
}

您忘记将 \n 替换为 NUL

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

还有另一个问题:考虑如果用户在按 Enter 之前输入了超过 11 个字符会发生什么。我让你发现自己是一种锻炼。

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

因此,null 如果您发现 \n 如下所示,则终止输入。

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

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

其他答案中提到的\n的问题不成立,如果您确实看到strcmp() return错误的指示,问题就变成了为什么?

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

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

|p|a|s|s|1|2|3|[=10=]|[=10=]|[=10=]|[=10=]|[=10=]| // `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|[=11=]|  // 'password' - too long by 1 character
                        ^     // end of legal definition of `password`

如果 password 数组有太多字符,即使在这种情况下,在 beyond[=48] 的位置将最后一个 char \n 替换为 NULL =] 字符串的合法定义,代码变为undefined behavior.

字符串函数专门用于 strings。当出现非 nul 终止的字符数组时,函数(在本例中为 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() 会指出。