我要做的就是要求输入密码并在输入超过10个字符时打印出错误信息。如果第一个输入短于10个字符,它可以工作。它只打印出输入并退出程序。如果输入超过10个字符,则会输出错误消息并要求输入新密码,但如果第二次尝试输入少于10个字符,则打印出输入,然后程序中断“Thread:1信号” SIGABRT“错误。我知道我不应该使用gets,但我试图找到一种方法来使我的代码使用它。
#include <stdio.h>
#define BUFFER_LENGTH 11
int main() {
int cont;
while (1) {
char line[BUFFER_LENGTH];
char *p;
printf("Enter Password: ");
p = gets (line);
if (strlen(p)>10) {
printf("Error! Password must be shorter than 10 characters! \n");
}else{
printf(p);
printf("\n");
break;
}
}
}
答案 0 :(得分:3)
如果用户输入超过10个字符,则最终会使用超出有效限制的内存。这正是你必须避免使用gets
的原因。有关该主题的更多信息,请参阅Why is the gets function so dangerous that it should not be used?。
将gets
行更改为:
fgets(line, sizeof(line), stdin);
然后,您不必担心用户输入超过10个字符。他们将被忽略。
如果您要将该用例作为用户错误处理,请更改line
的大小,但仍使用fgets
。
更新,感谢@chux
如果用户输入的内容少于11个字符,则为
行 fgets(line, sizeof(line), stdin);
不仅会读取字符,还会在其中包含结尾的换行符。您必须添加一些代码来修剪line
中的换行符。
// Trim the newline character from user input.
size_t len = strlen(line);
if ( len > 0 && line[len-1] == '\n' )
{
line[len-1] = '\0';
}
答案 1 :(得分:2)
要检测是否输入了超过n
个字符,代码必须
至少阅读n+1
个非控制字符。
处理过多的字符。
OP的代码不应使用gets()
。这是一个过时的功能,不会阻止缓冲区溢出。
void GetPrintPW(void) {
// +1 for the null character.
char pw[PASSWORD_MAX_LENGTH + 1];
size_t i = 0;
bool too_long = false;
int bad_char = EOF;
int ch;
// Note: All characters in the line are consumed. Only the first `n` are saved.
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
// This would be a good place to add code to check if the character is "good".
if (!isprint(ch)) bad_char = ch;
if (i < PASSWORD_MAX_LENGTH) pw[i++] = ch;
else too_long = true;
}
pw[i] = '\0';
if (bad_char != EOF) {
printf("Error! Bad character, code %d\n", bad_char);
} else if (too_long) {
// Avoid `printf(only_some_string)`
puts("%Error! Password must be shorter than 10 characters!");
} else {
// this is BAD! as a % in pw will cause UB with `printf()`
// printf(pw);
printf("'%s'\n", pw);
}
// Always a good idea to scrub data after using a password to prevent memory snooping.
memset(pw, 0, sizeof pw);
}
PW注意:不要使用getline()
来读取密码,因为代码会失去对存储密码的缓冲区的控制权。使用普通字符数组并随后擦洗。使用malloc()
,realloc()
等也会遇到类似的问题。
好的操作系统将具有在每个功能级别读取密码的特殊功能,需要清除任何缓冲区数据。
答案 2 :(得分:0)
如果您使用gets
,line
需要足够大才能容纳用户在点击返回之前可能输入的所有可能字符。那是多少?限制接近无限。请改用fgets
。