C检查用户输入错误

时间:2016-01-29 22:30:15

标签: c runtime-error

我要做的就是要求输入密码并在输入超过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;
        }
    }
}

3 个答案:

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

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

  2. 处理过多的字符。

  3. 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)

如果您使用getsline需要足够大才能容纳用户在点击返回之前可能输入的所有可能字符。那是多少?限制接近无限。请改用fgets