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字符,代码必须

  1. 读取至少n+1非控制字符。

  2. 处理过多的字符。

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