要求密码必须包含大写字母,数字和“ $”符号。一切正常(除非用户出于某种原因输入空格,否则将不胜感激),但是idk我的代码有多有效。我是C的新手,有什么建议吗? (除了将密码设置为非常高的值或强迫用户遵守限制之外,还有其他方法可以为我的密码设置“最大长度”吗?)
int main(void){
int maxlength = 15;
char password[maxlength];
int index = 0;
int x = 0;
int y = 0;
int z = 0;
printf("Enter Password: "); //Mike$4
scanf(" %s", password);
do{ // If index is strlen, then we checked every char of pw
// Ex. Password is length 6, then index 0 - 5 will be checked
if(index == strlen(password) && x>0 && y>0 && z>0){
printf("Good password!");
break;
}
if(index == strlen(password) && (x==0 || y==0 || z==0)){
printf("BAD PASSWORD");
break;
}
if(isupper(password[index]) || isdigit(password[index]) ||
password[index] == '$'){
if(isupper(password[index])){
x++; index++;
continue;}
if(isdigit(password[index])){
y++; index++;
continue;}
if(password[index] == '$'){
z++; index++;
continue;}
}else{index++;
continue;
}
}while(index <= strlen(password));
return 0;}
基本上,每次满足要求时,我只是通过增加x,y或z来指出它,如果在密码末尾,它们都至少有1,那么这是一个很好的密码。
谢谢!
我在问是否有更好的方法编写此代码,因为我在学校的下一门CS课程也将根据效率进行评分,因此我想确保我知道是什么使C代码有效。当然,如何处理密码中的空格。
答案 0 :(得分:1)
我的代码效率如何....
常见的编码陷阱是性能,而C代码却具有未定义行为(UB)。首先修复UB,然后解决效率问题。
缓冲区溢出
scanf(" %s", password);
没有提供宽度限制。 15个字符(或更多)的密码将通过尝试在password[]
外部写入来调用UB。
负char
在编码早期,人们不太可能遇到char
带有负值的情况,但是当它们发生时,is...(int ch)
函数是一个问题。在这里,ch
的值必须在unsigned char
范围或EOF
范围内,否则UB会再次出现。
// isupper(password[index])
isupper((unsigned char) password[index])
考虑到UB,scanf(" %s", password);
可以轻松地花费while循环时间的100倍。因此,通过微优化优化代码边界。
避免使用O(n * n)代码
假设密码的长度为n
,然后要查找字符串的长度,则必须通过n
遍历所有strlen()
字符。另外,代码还在执行n
循环,每次迭代都调用strlen()
。就是n*n
时间。
当今许多编译器会发现password
不会在循环中更改,因此将记住strlen(password)
的结果,从而防止了n*n
的迭代。
do{
if(index == strlen(password) && x>0 && y>0 && z>0){
...
} while(index <= strlen(password));
不过,在循环外替换一次非迭代代码或计算长度一样简单。
size_t len = strlen(password);
do {
// if(index == strlen(password) ...
if(password[index] != '\0' ...
// or
if(index == len ...
// }while(index <= strlen(password));
} while(index <= len);
使用这样的短字符串,长度为int
的类型就可以了,但是对于包括 string 在内的常规数组代码,size_t
是用于数组索引的合适大小的类型和长度。
使用诸如upper_count
之类的信息性名称而不是x
可以产生更好的代码。
示例未经测试的备用代码。代码专门将fgetc()
与其他输入方式结合使用,以此作为迈向安全性的一步-还有更多步骤。
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#define PWD_N 6
int main(void) {
size_t maxlength = 15;
char password[maxlength + 1]; // add 1 for \0
bool upper = false;
bool digit = false;
bool dollar = false;
bool length_ok = true;
printf("Enter Password: "); //Mike$4
fflush(stdout);
size_t i = 0;
for (;;) {
int ch = fgetc(stdin);
if (ch == '\n' || ch == EOF) {
break;
}
if (i < sizeof password - 1) {
password[i++] = ch;
upper |= isupper(ch);
digit |= isdigit(ch);
dollar |= ch == '$';
} else {
length_ok = false; // too long
}
}
password[i] = '\0';
if (i == PWD_N && length_ok && upper && digit && dollar) {
printf("Good password!\n");
} else {
printf("BAD PASSWORD\n");
}
return 0;
}