在编程中,用户登录验证是一个常见的功能。以下是一个简单的用户登录验证程序,它使用了 scanf
函数获取用户输入的密码,并通过 strcmp
函数比较用户输入的密码和预设密码是否匹配。我们将对这个程序进行一些优化,并详细解释这些优化措施。
首先,让我们回顾一下原始的程序代码:
#include<stdio.h>
#include<string.h>
int main() {
int i = 0;
char password[20] = { 0 };
for (i = 0; i < 3; i++) {
printf("请输入密码(3次机会);\n");
scanf("%s", password);
if (strcmp(password, "123456") == 0) { // 检查密码是否匹配
printf("登陆成功!!!\n");
break;
}
else {
printf("用户或密码错误\n");
}
}
if (i > 3) {
printf("输入次数已用完!请退出程序!\n");
}
return 0;
}
虽然这个程序能够完成基本的登录验证功能,但我们可以对其进行以下优化:
- 防止缓冲区溢出:
scanf
函数在读取字符串时可能会导致缓冲区溢出。为了防止这种情况,我们可以限制scanf
读取的字符数量,如下所示:
scanf("%19s", password); // 限制最多读取19个字符(留一个字节给 '\0')
- 添加密码输入掩码:为了提高用户输入密码时的安全性,我们可以使用
getch
函数逐个读取字符,并显示星号(*)作为掩码,如下所示:
#include <conio.h> // 引入头文件以使用 getch 函数
// ...
for (i = 0; i < 3; i++) {
printf("请输入密码(3次机会);\n");
for (int j = 0; j < sizeof(password) - 1; j++) { // 使用循环读取每个字符
char ch = getch(); // 获取一个字符
if (ch == '\r' || ch == '\n') { // 如果是回车,则结束输入
password[j] = '\0'; // 结束字符串
break;
}
else if (ch == '\b') { // 如果是退格键,则删除前一个字符
if (j > 0) {
printf("\b \b"); // 删除星号并回退光标
j--;
}
}
else {
password[j] = ch; // 将字符添加到密码中
printf("*"); // 显示星号作为掩码
}
}
// ...
}
- 提供更明确的错误提示:在用户输入错误时,我们可以通过修改错误提示信息来提供更明确的反馈:
if (strcmp(password, "123456") != 0) { // 检查密码是否不匹配
printf("密码错误,请重新输入\n");
}
程序代码如下:
#include<stdio.h>
#include<string.h>
#include <conio.h> // 引入头文件以使用 getch 函数
int main() {
int i = 0;
char password[20] = { 0 };
for (i = 0; i < 3; i++) {
printf("请输入密码(3次机会);\n");
for (int j = 0; j < sizeof(password) - 1; j++) {
char ch = getch();
if (ch == '\r' || ch == '\n') {
password[j] = '\0';
break;
}
else if (ch == '\b') {
if (j > 0) {
printf("\b \b");
j--;
}
}
else {
password[j] = ch;
printf("*");
}
}
if (strcmp(password, "123456") != 0) {
printf("密码错误,请重新输入\n");
}
else {
printf("登陆成功!!!\n");
break;
}
}
if (i > 3) {
printf("输入次数已用完!请退出程序!\n");
}
return 0;
}
总结,通过对原始的用户登录验证程序进行上述优化,我们可以提高其安全性、用户体验和错误提示的明确性。