通过给定的scanset在scanf()处检测到太长的字符串

时间:2018-12-01 15:53:34

标签: c scanf

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

我尝试的是将输入读入临时文件 char数组并将scanset定义为4[a-z ], 这样就只能读取正确的字符 还有一个字符,以便检查最大 所需字符数已读取。 即如果此临时数组中的最后一个元素 不为空,用户输入大于3。

问题:
当用户输入3个正确的字符时 还有第四个错误的字符,第四个字符将不会被读取, 因此,我们读取了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()和scanset来解决,欢迎您的想法!

1 个答案:

答案 0 :(得分: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
  }
}