【问题标题】:Detect too long string at scanf() by given scanset通过给定的扫描集在 scanf() 检测太长的字符串
【发布时间】:2018-12-01 15:53:33
【问题描述】:

场景:
我正在尝试验证一些用户输入。 在我的情况下,用户只被允许 输入 0 到 3 个小写字符, 可选地包括空格。 在正则表达式中:^[a-z ]{0,3}$
如果用户输入超过 3 个字符或 输入字符串包含无效值, 在每种情况下都有不同的return-value 和 必须打印错误消息。

我尝试将输入读入临时 char 数组并将扫描集定义为4[a-z ], 这样只会读取正确的字符 还有一个字符,以检查最大值是否 已读取所需字符数。 IE。如果这个临时数组中的最后一个元素 不为空用户输入大于 3。

问题:
当用户输入 3 个正确字符时 和第 4 个错误的字符,第 4 个不会被读取, 因此我们读取了 3 个有效字符, 我们“据称”从未读取过无效字符并且 读取字符的长度也是有效的, 一切都很难,当然不是!

代码:

//--------------------------------------
int scan_input(char* char_array)
{
  int status = 0;
  int max_size = 3;
  char temp_array[max_size+1];

  // Print system prompt:
  printf("plain text: ");
  // Read user input:
  status = scanf("%4[a-z ]", temp_array);

  if (temp_array[max_size] != '\0')
  {
    printf("[ERR] too many characters\n");
    return -1;
  }

  if (status != 1)
  {
    printf("[ERR] invalid characters\n");
    return -2;
  }

  strcpy(char_array,temp_array);
  printf("[OK]  Input is valid!\n");
  return 0;
}

输出:

$ gcc -Wall -std=c11 application.c && ./a.out 
plain text: abcD
[OK]  Input is valid!

感谢每一个修复这个盲点的提示!

PS.: 如果您知道解决此问题的更好方法,而不是使用 scanf() 和扫描集,欢迎提出您的想法!

【问题讨论】:

  • 你有一个缓冲区溢出。使用输入“abcD”,scanf 将向temp_array所有 元素写入“a”、“b”、“c”和“D”......它会(尝试) 在数组外写入终止的'\0'(覆盖一些变量,使测试无结果,唱国歌,...)

标签: c scanf


【解决方案1】:

验证一些用户输入

将输入与解析分开

  • 使用宽缓冲区和fgets()

    char buf[80];
    if (fgets(buf, sizeof buf, stdin)) {
      // we have some input
    
  • 然后解析并使用记录扫描位置的"%n"测试成功。

      int max_size = 3;
      char temp_array[max_size+1];
      int n = 0;
      temp_array[0] = '\0';
      sscanf(buf, "%3[a-z ]%n", temp_array, &n);
      bool success = buf[n] == '\n' || buf[n] == '\0';
    

如果sscanf() 没有扫描任何内容,n == 0 和之前的temp_array[0] = 0 将确保空字符

如果扫描成功,n > 0 和代码会检查下一个字符。


替代入住scanf()

status = scanf("%3[a-z ]", temp_array);

// When nothing read, form "" string   
if (status != 1) {
  temp_array[0] = '\0';
}

bool success = true;
if (status == EOF) {
  success = false;
} else {
  // consume rest of line, noting if extra junk followed
  int next_ch;
  while ((next_ch = fgetc(stdin)) != '\n' && next_ch != EOF) {
    success = false;  //Extra junk
  }
}

【讨论】:

    猜你喜欢
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    相关资源
    最近更新 更多