C检查用户输入错误
我想要做的就是要求输入密码,如果输入超过10个字符,则打印出错误信息。 如果第一个输入短于10个字符,它可以工作。 它只打印出输入并退出程序。 如果输入超过10个字符,则会输出错误消息并要求输入新密码,但如果第二次尝试输入少于10个字符,则打印出输入,然后程序中断“Thread:1信号” SIGABRT“错误。 我知道我不应该使用获取,但我试图找到一种方法来使我的代码使用它。
#include #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; } } }
如果用户输入超过10个字符,则最终使用超出有效限制的内存。 这正是你必须避免使用gets
的原因。 请参阅为什么获取function如此危险以至于不应该使用它? 有关该主题的更多信息。
将gets
行更改为:
fgets(line, sizeof(line), stdin);
然后,您不必担心用户输入超过10个字符。 他们将被忽略。
如果要将该用例作为用户error handling,请更改行的大小但仍使用fgets
。
更新,感谢@chux
如果用户在您的案例中输入少于11个字符,则为该行
fgets(line, sizeof(line), stdin);
不仅会读取字符,还会在其中包含结尾的换行符。 你必须添加一些代码来修改换行符。
// Trim the newline character from user input. size_t len = strlen(line); if ( len > 0 && line[len-1] == '\n' ) { line[len-1] = '\0'; }
要检测是否输入了超过n
字符,代码必须
-
读取至少
n+1
非控制字符。 -
处理过多的字符。
OP的代码不应该使用gets()
。 它是一个过时的function,不会阻止缓冲区溢出。
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()
来读取密码,因为代码会失去对存储密码的缓冲区的控制。 使用普通的char数组并在之后进行擦洗。 使用malloc()
, realloc()
等也可能有类似的问题。
好的操作系统将具有在每个function级别读取密码的特殊function,需要擦除任何缓冲区数据。
如果使用gets
,则line
必须足够大以容纳用户在返回之前可以输入的所有可能字符。 这有多少? 限制接近无限。 请改用fgets
。