数字验证 - 无尽循环

时间:2012-07-15 01:25:36

标签: c validation

我有这段代码来验证用户输入。条件:输入的值应仅为零或正数。不接受负值和字母字符。

这是我的代码,只是继续循环:

#include <stdio.h>

int main ()
{
   int a, b, c, d;

   printf ("enter value for a:");
   do {
      b = 0;
      scanf ("%d", &a);
      if (!isdigit(a)) {
         printf("Number must be numeric!:\n");
         b++;
      }
      else if (a < 0) {
         printf ("number must be postive\n");
         b++;
      } else {
         printf("\neverything is goood\n");
      }
   } while (b != 0);
}

5 个答案:

答案 0 :(得分:4)

isdigit()期待ASCII编码字符,但scanf %d参数将ASCII编码数字(字符串)转换为实际数字。

即。如果输入'1',ASCII代码为0x31,则scanf("%d",...会将其转换为值1。 ASCII码1为数字。

要解决此问题,请:

  • 设置a类型char并使用scanf格式说明符%c,然后isdigit()将按您的要求执行。
  • 使用strtol读取多个字符,并使用char **endptr参数执行自己的错误检查。

此外,您应该打开编译器警告并包含包含isdigit()函数ctype.h的头文件。

答案 1 :(得分:1)

一旦用户犯了错误,b总是&gt; 0.在输入正确的信息后(即在你的printf(“\ neverything good / n”)之后,你需要添加一个设置b = 0的行;声明。只需确保将{&amp;}添加到之前的else语句中它,因此printf&amp; new b = 0;语句将包含在该分支中)

答案 2 :(得分:1)

以下是我可以发现的代码问题:

  1. 您将scanf%d格式说明符一起使用,该格式说明符已将输入解析为整数值。因此,无需检查isdigit是否为数字。实际上,isdigit正在检查十进制数字符,因此您的使用不正确。
  2. 您永远不会检查scanf返回。你应该。如果出现错误(即值为非数字),则不会从流中删除输入。换句话说,你会一遍又一遍地试图解析相同的坏值。
  3. 您有未使用的变量,但忘记包含某些头文件。但在你的情况下这些都是小事(但在某些情况下可能很重要!)。
  4. 话虽如此,这里有一些可能适合你的代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    static void skip_input(FILE *stream)
    {
        int c;
        do {
            c = fgetc (stream);
        } while (c != EOF && c != '\n');
    }
    
    int main()
    {
        int a;
        int r;
    
        printf("Please enter a value: ");
    
        for (;;) {
            r = scanf("%d", &a);
            if (r == EOF)
                return EXIT_FAILURE;
            if (r != 1) {
                printf("Number must be numeric!\n");
                skip_input(stdin);
            } else if (a < 0) {
                printf("Number must be postive\n");
                skip_input(stdin);
            } else {
                printf("Everything is goood\n");
                break;
            }
        }
    
        return EXIT_SUCCESS;
    }
    

    希望它有所帮助。

答案 3 :(得分:0)

您正在使用b作为错误标记。

在“一切都很好”中,尝试设置b=0;
此外,如果您这样做,您可以摆脱b++;行,只需初始化b=1;
如果你需要报告用户搞砸了多少次,你应该只做b++,我认为你不需要它?

答案 4 :(得分:0)

这里有几个问题。

第一个是没有检查scanf()的返回值。如果输入可用,则scanf返回已分配的变量数,在这种情况下可以是0或1(因为您只是尝试分配一个变量)。如果用户输入一个非数字字符,那么循环将重复执行,而不会等待更多的用户输入,因为有可用的输入,但它永远不会匹配您的“%d”转换。如果你想使用scanf(),那么你必须检查返回值。如果返回值为零,则输入非数字值,这意味着您必须通过读取直到行的末尾从输入缓冲区中清除该值。如果返回值等于EOF,则表明发生了I / O错误或者您到达了流的末尾。如果返回值为1,那么您知道该值是数字,这使我遇到下一个问题。

例程isdigit()采用整数参数,但它期望整数值表示一个字符。由于您使用scanf()将输入转换为整数,因此存储在a中的值不再表示字符;它代表一个实际数字。因此,如果用户输入对应于数字字符的数字,则对isdigit()的调用将仅返回true值。在我的语言环境中,这意味着只有当用户输入48到57之间的数字时,验证才会成功。如果你正在使用scanf(),则不需要进行isdigit()检查,因为只有当用户输入数值时,scanf()才会返回值1。

老实说,但是,我不会使用scanf()来读取用户输入,如果我可以准确地避免它,因为如果用户输入错误就需要刷新输入缓冲区。我不完全确定你的要求是什么,但我会假设你应该从命令行读取一个正整数,并且数字位数无关紧要。

在这种情况下,您可能希望使用fgets()来读取用户输入,然后使用strtol()将值转换为带符号的长整数并同时执行验证:

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>

int main () {
  long result;
  long len;
  int is_valid = 0;
  char buf[128];
  char *arg;
  char *end;

  while (!is_valid) {

    /* Prompt the user for the integer. */
    printf("Enter a non-negative integer: ");
    if (fgets(buf, sizeof(buf), stdin) == NULL) {
      printf("Giving up so soon?\n");
      break;
    }

    /* Verify that the input doesn't exceed our buffer length. */
    len = strlen(buf);
    if (buf[len] != '\n') {
      printf("Input buffer length exceeded - aborting.\n");
      exit(1);
    }

    /* Skip any leading whitespace. */
    for (arg = buf; isspace(*arg); arg++);

    /* Attempt to convert the argument. */
    errno = 0;
    result = strtol(arg, &end, 10);
    if (errno == EINVAL) {
      printf("Please enter a numeric value.\n");
      continue;
    }
    if (errno == ERANGE) {
      printf("Numeric value out of range.\n");
      continue;
    }

    /* Check for non-whitespace characters after the end of the integer. */
    for (; isspace(*end); end++);
    if (*end != '\0') {
      printf("Please enter a numeric value.\n");
      continue;
    }

    /* Verify that the number is non-negative. */
    if (result < 0) {
      printf("Please enter a positive value.\n");
      continue;
    }

    /* The number is valid. */
    printf("Excellent!\n");
    is_valid = 1;
  }

  return 0;
}

这并不完美;如果超过输入缓冲区长度则中止不完全是用户友好的。但是,它应该处理验证问题。