有人可以解释一下为什么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");
}
}
答案 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
存储在输入缓冲区中,因此pass123
和pass123\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()
将会表明。