【问题标题】:Check if input is integer type in C检查输入是否是C中的整数类型
【发布时间】:2011-05-03 14:22:57
【问题描述】:

问题是我不能使用 atoi 或任何其他类似的函数(我很确定我们应该依赖数学运算)。

 int num; 
 scanf("%d",&num);
 if(/* num is not integer */) {
  printf("enter integer");
  return;
 }

我试过了:

(num*2)/2 == num
num%1==0
if(scanf("%d",&num)!=1)

但这些都不起作用。

有什么想法吗?

【问题讨论】:

  • “这些都不起作用”是什么意思?最后一个是怎么试的?
  • @David 我把它们放在 if 语句中,有什么令人困惑的地方?
  • “整数类型”是什么样的输入?一个只由数字组成的?前面可以加减号吗?
  • 您列出了两个条件和一个 if 语句。我假设您没有在 if 语句中包含 if 语句,所以我不知道您在那里做了什么。 (您只是替换了 if 语句,还是比这更重要?)除了“这些都不起作用”之外,您也没有提供任何故障模式的线索。没有编译?运行时错误?没有按您预期的方式工作(如果是,您的预期是什么?)?
  • 我知道我迟到了,但我想你“不能”(意思是:不允许)使用atoi(),因为这个想法是你通过步行“手动”进行检查通过字符并检查它们是否在 0-9 范围内。因此很可能scanf() 也不应该被使用。

标签: c input integer


【解决方案1】:

num 将始终包含一个整数,因为它是一个int。您的代码真正的问题是您没有检查scanf 返回值。 scanf 返回成功读取的项目数,因此在这种情况下,它必须返回 1 作为有效值。如果不是,则输入了一个无效的整数值,并且num 变量可能没有被更改(即仍然具有任意值,因为您没有对其进行初始化)。

在您的评论中,您只想允许用户输入一个整数,然后输入回车键。不幸的是,这不能简单地通过scanf("%d\n") 实现,但这里有一个技巧:

int num;
char term;
if(scanf("%d%c", &num, &term) != 2 || term != '\n')
    printf("failure\n");
else
    printf("valid integer followed by enter key\n");

【讨论】:

  • 不,我检查了返回值,即使对于像“2k”这样的非整数,它也是“1”。
  • @sombe:当scanf 正在读取一个数字并检测到一个非数字字符时,它会简单地停在那里并将其留给流(在这种情况下,只需“返回”2)
  • @eq 没关系,如果用户插入非整数键,我必须检测它并打印错误。
  • @sombe:已编辑以允许您的用例。
  • 我试过了,它确实有效,我真的希望它没问题。非常感谢。
【解决方案2】:

您需要先将输入读取为字符串,然后解析字符串以查看它是否包含有效的数字字符。如果是,那么您可以将其转换为整数。

char s[MAX_LINE];

valid = FALSE;
fgets(s, sizeof(s), stdin);
len = strlen(s);
while (len > 0 && isspace(s[len - 1]))
    len--;     // strip trailing newline or other white space
if (len > 0)
{
    valid = TRUE;
    for (i = 0; i < len; ++i)
    {
        if (!isdigit(s[i]))
        {
            valid = FALSE;
            break;
        }
    }
}

【讨论】:

  • 有没有办法用正则表达式实现这一点?
  • @sombe:当然,使用正则表达式验证整数只是\d+。但是 C 有正则表达式吗?
  • 请不要建议使用危险的gets()
  • @sombe 您确实需要这样做,但在检查它是否有效后,您需要添加一个 sscanf(s, "%d", num); ,它将从中生成一个整数。
  • @sombe,您能告诉我们实际要求吗?我的猜测是你也应该处理字符串->十进制转换(这就是我写作业的方式)
【解决方案3】:

使用带有%d 转换说明符的scanf 来执行此操作存在几个问题:

  1. 如果输入字符串以有效整数开头(如“12abc”),则从输入流中读取“12”并转换并赋值给numscanf将返回1,所以当你(可能)不应该表示成功时,你会表示成功;

  2. 如果输入字符串以数字开头,那么scanf将不会从输入流中读取任何个字符,num会不改变,返回值为0;

  3. 您没有指定是否需要处理非十进制格式,但如果您必须处理八进制或十六进制格式 (0x1a) 的整数值,这将不起作用。 %i 转换说明符处理十进制、八进制和十六进制格式,但您仍然遇到前两个问题。

首先,您需要将输入读取为字符串(最好使用fgets)。如果不允许您使用atoi,您可能也不允许使用strtol。因此,您需要检查字符串中的每个字符。检查数字值的安全方法是使用 isdigit 库函数(还有 isodigitisxdigit 函数分别用于检查八进制和十六进制数字),例如

while (*input && isdigit(*input))
   input++;    

(如果你甚至不被允许使用isdigitisodigitisxdigit,那么就责备你的老师/教授让作业变得比实际需要的更难)。

如果您需要能够处理八进制或十六进制格式,那么它会变得更复杂一些。 C 约定是八进制格式有一个前导 0 数字,十六进制格式有一个前导 0x。因此,如果第一个非空白字符是 0,则必须先检查下一个字符,然后才能知道要使用哪种非十进制格式。

基本大纲是

  1. 如果第一个非空白字符不是“-”、“+”、“0”或非零十进制数字,则这不是有效的整数字符串;
  2. 如果第一个非空白字符是'-',那么这是一个负值,否则我们假设一个正值;
  3. 如果第一个字符是“+”,那么这是一个正值;
  4. 如果第一个非空白和非符号字符是非零十进制数字,则输入为十进制格式,您将使用isdigit检查剩余字符;
  5. 如果第一个非空白和非符号字符是“0”,则输入为八进制或十六进制格式;
  6. 如果第一个非空白和非符号字符是“0”,下一个字符是从“0”到“7”的数字,则输入为八进制格式,您将使用isodigit检查剩余的字符;
  7. 如果第一个非空白和非符号字符是0,第二个字符是xX,则输入为十六进制格式,您将使用isxdigit检查剩余字符;
  8. 如果任何剩余的字符不满足上面指定的检查函数,那么这不是一个有效的整数字符串。

【讨论】:

    【解决方案4】:

    首先问问自己,你会如何曾经期望这段代码返回一个整数:

    int num; 
    scanf("%d",&num);
    

    您将变量指定为整数类型,然后是 scanf,但为整数 (%d)。

    此时它还可能包含什么?

    【讨论】:

    • 抱歉,人们似乎对这个答案赞不绝口,但我完全预料到你从算法中写的内容,但它没有用。我应该检查该值,使其永远不是非整数,并且您的解决方案不会削减它。我错过了什么吗?请解释一下。
    • @sombe:您缺少的是scanf("%d",&amp;num) 只会将整数值存储到num 根据定义该值是否与输入字符串有任何关系是一个悬而未决的问题。如果您输入带有前导数字的内容(如“12efg”),scanf 将读取、转换并分配前导“12”,将“efg”留在输入流中。如果输入字符串不是以数字开头(例如“ab123”),则将读取输入字符串的none,并且num 将包含它在调用之前的任何值(其中仍然是一个整数)。
    • “此时它还可能包含什么?” --> 一个陷阱值 - 虽然我已经多年没有看到 int 使用陷阱了。
    【解决方案5】:

    如果有人提出这个问题,我写了一个程序,如果用户的输入不是整数,它会一直要求输入一个数字,并在接受一个整数时结束

    #include<stdlib.h>
    #include<stdio.h>
    #include<stdbool.h>
    
    bool digit_check(char key[])
    {
        for(int i = 0; i < strlen(key); i++)
        {
            if(isdigit(key[i])==0)
            {
                return false;
            }
        }
        return true;
    }
    
    void main()
    {
        char stroka[10];
        do{
            printf("Input a number: ");
            scanf("%s",stroka);}
        while (!digit_check(stroka));
        printf("Number is accepted, input finished!\n");
        system("pause");
    }
    

    【讨论】:

      【解决方案6】:

      我看了上面大家的输入,很有用,做了一个适合我自己应用的函数。该函数实际上只是评估用户的输入不是“0”,但对于我的目的来说已经足够了。希望这会有所帮助!

      #include<stdio.h>
      
      int iFunctErrorCheck(int iLowerBound, int iUpperBound){
      
      int iUserInput=0;
      while (iUserInput==0){
          scanf("%i", &iUserInput);
          if (iUserInput==0){
              printf("Please enter an integer (%i-%i).\n", iLowerBound, iUpperBound);
              getchar();
          }
          if ((iUserInput!=0) && (iUserInput<iLowerBound || iUserInput>iUpperBound)){
              printf("Please make a valid selection (%i-%i).\n", iLowerBound, iUpperBound);
              iUserInput=0;
          }
      }
      return iUserInput;
      }
      

      【讨论】:

      • 代码在使用iUserInput之前应该检查scanf("%i", &amp;iUserInput)的返回值。
      【解决方案7】:

      试试这个...

      #include <stdio.h>
      
      int main (void)
      {
          float a;
          int q;
      
          printf("\nInsert number\t");
          scanf("%f",&a);
      
          q=(int)a;
          ++q;
      
          if((q - a) != 1)
              printf("\nThe number is not an integer\n\n");
          else
              printf("\nThe number is an integer\n\n");
      
          return 0;
      }
      

      【讨论】:

      • scanf("%f",&amp;a);a 的无效数字输入未初始化,q=(int)a; 未定义。代码应该在使用a之前检查scanf("%f",&amp;a)的返回值。
      【解决方案8】:

      我猜这是一个更人性化的:

      #include<stdio.h>
      
      /* This program checks if the entered input is an integer
       * or provides an option for the user to re-enter.
       */
      
      int getint()
      {
        int x;
        char c;
        printf("\nEnter an integer (say -1 or 26 or so ): ");
        while( scanf("%d",&x) != 1 )
        {
          c=getchar();
      
          printf("You have entered ");
          putchar(c);
          printf(" in the input which is not an integer");
      
          while ( getchar() != '\n' )
           ; //wasting the buffer till the next new line
      
          printf("\nEnter an integer (say -1 or 26 or so ): ");
      
        }
      
      return x;
      }
      
      
      int main(void)
      {
        int x;
        x=getint();
      
        printf("Main Function =>\n");
        printf("Integer : %d\n",x);
      
       return 0;
      }
      

      【讨论】:

      • while( scanf("%d",&amp;x) != 1 ) 循环是无限循环,如果stdin 关闭,scanf("%d",&amp;x) 将永远返回EOF。还有while ( getchar() != '\n' )
      【解决方案9】:

      我使用gets和远离scanf的麻烦开发了这个逻辑:

      void readValidateInput() {
      
          char str[10] = { '\0' };
      
          readStdin: fgets(str, 10, stdin);
          //printf("fgets is returning %s\n", str);
      
          int numerical = 1;
          int i = 0;
      
          for (i = 0; i < 10; i++) {
              //printf("Digit at str[%d] is %c\n", i, str[i]);
              //printf("numerical = %d\n", numerical);
              if (isdigit(str[i]) == 0) {
                  if (str[i] == '\n')break;
                  numerical = 0;
                  //printf("numerical changed= %d\n", numerical);
                  break;
              }
          }
          if (!numerical) {
              printf("This is not a valid number of tasks, you need to enter at least 1 task\n");
              goto readStdin;
          }
          else if (str[i] == '\n') {
              str[i] = '\0';
              numOfTasks = atoi(str);
              //printf("Captured Number of tasks from stdin is %d\n", numOfTasks);
          }
      }
      

      【讨论】:

      • str[10] 不足以容纳较大的 int 值。
      【解决方案10】:
      printf("type a number ");
      int converted = scanf("%d", &a);
      printf("\n");
      
      if( converted == 0) 
      {
          printf("enter integer");
          system("PAUSE \n");
          return 0;
      }
      

      scanf() 返回匹配的格式说明符的数量,因此如果输入的文本不能解释为十进制整数,则返回零

      【讨论】:

        【解决方案11】:

        我一直在寻找一个只使用循环和 if 语句的更简单的解决方案,这就是我想出的。该程序还可以处理负整数,并正确拒绝任何可能同时包含整数和其他字符的混合输入。


        #include <stdio.h>
        #include <stdlib.h> // Used for atoi() function
        #include <string.h> // Used for strlen() function
        
        #define TRUE 1
        #define FALSE 0
        
        int main(void)
        {
            char n[10]; // Limits characters to the equivalent of the 32 bits integers limit (10 digits)
            int intTest;
            printf("Give me an int: ");
        
            do
            {        
                scanf(" %s", n);
        
                intTest = TRUE; // Sets the default for the integer test variable to TRUE
        
                int i = 0, l = strlen(n);
                if (n[0] == '-') // Tests for the negative sign to correctly handle negative integer values
                    i++;
                while (i < l)
                {            
                    if (n[i] < '0' || n[i] > '9') // Tests the string characters for non-integer values
                    {              
                        intTest = FALSE; // Changes intTest variable from TRUE to FALSE and breaks the loop early
                        break;
                    }
                    i++;
                }
                if (intTest == TRUE)
                    printf("%i\n", atoi(n)); // Converts the string to an integer and prints the integer value
                else
                    printf("Retry: "); // Prints "Retry:" if tested FALSE
            }
            while (intTest == FALSE); // Continues to ask the user to input a valid integer value
            return 0;
        }
        

        【讨论】:

        • scanf("%d"... 将接受 "+123" "-1234567890",此答案也无法正确处理。
        【解决方案12】:

        只需检查您的号码是否与浮动版本有任何区别。

        float num; 
        scanf("%f",&num);
        
        if(num != (int)num) {
            printf("it's not an integer");
            return;
        }
        

        【讨论】:

          【解决方案13】:

          此方法适用于除零之外的所有内容(整数甚至双精度数)(称为无效):

          while 循环仅用于重复的用户输入。基本上它检查整数 x/x = 1。如果是(就像使用数字一样),它是一个整数/双精度数。如果不是,那显然不是。零没有通过测试。

          #include <stdio.h> 
          #include <math.h>
          
          void main () {
              double x;
              int notDouble;
              int true = 1;
              while(true) {
                  printf("Input an integer: \n");
                  scanf("%lf", &x);
                  if (x/x != 1) {
                      notDouble = 1;
                      fflush(stdin);
                  }
                  if (notDouble != 1) {
                      printf("Input is valid\n");
                  }
                  else {
                      printf("Input is invalid\n");
                  }
                  notDouble = 0;
              }
          }
          

          【讨论】:

          • scanf("%lf", &amp;x);x 的无效数字输入未初始化,x/x 未定义。
          【解决方案14】:

          我遇到了同样的问题,终于想通了:

          #include <stdio.h>
          #include <conio.h>
          
          int main ()
          {
              int x;
              float check;
              reprocess:
              printf ("enter a integer number:");
              scanf ("%f", &check);
              x=check;
              if (x==check)
              printf("\nYour number is %d", x);
              else 
              {
                   printf("\nThis is not an integer number, please insert an integer!\n\n");
                   goto reprocess;
              }
              _getch();
              return 0;
          }
          

          【讨论】:

          • conio.h 不保证分布在所有平台上。
          • scanf ("%f", &amp;check); 会将"987654321" 之类的输入四舍五入到最接近的float 值,而不使用printf("\nYour number is %d", x); 打印原始值
          【解决方案15】:

          我找到了一种使用 atoi() 函数检查给定输入是否为整数的方法。

          将输入读取为字符串,并使用 atoi() 函数将字符串转换为整数。

          atoi()函数如果输入的字符串包含整数则返回整数,否则返回0。可以查看atoi()函数的返回值来判断给定的输入是否为整数。

          还有很多函数可以将字符串转换成long、double等,更多请查看标准库“stdlib.h”。

          注意:它仅适用于非零数字。

          #include<stdio.h>
          #include<stdlib.h>
          
          int main() {
              char *string;
              int number;
          
              printf("Enter a number :");
              string = scanf("%s", string);
          
              number = atoi(string);
          
              if(number != 0)
                  printf("The number is %d\n", number);
              else
                  printf("Not a number !!!\n");
              return 0;
          }
          

          【讨论】:

          • 没有分配给string的内存,所以scanf("%s", string);是UB。
          猜你喜欢
          • 2013-11-16
          • 2017-10-30
          • 1970-01-01
          • 2016-05-19
          • 1970-01-01
          相关资源
          最近更新 更多