检查输入是不是是C中的整数类型
Posted
技术标签:
【中文标题】检查输入是不是是C中的整数类型【英文标题】: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()
也不应该被使用。
【参考方案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
来执行此操作存在几个问题:
如果输入字符串以有效整数开头(如“12abc”),则从输入流中读取“12”并转换并赋值给num
,scanf
将返回1,所以当你(可能)不应该表示成功时,你会表示成功;
如果输入字符串不以数字开头,那么scanf
将不会从输入流中读取任何个字符,num
会不改变,返回值为0;
您没有指定是否需要处理非十进制格式,但如果您必须处理八进制或十六进制格式 (0x1a) 的整数值,这将不起作用。 %i
转换说明符处理十进制、八进制和十六进制格式,但您仍然遇到前两个问题。
首先,您需要将输入读取为字符串(最好使用fgets
)。如果不允许您使用atoi
,您可能也不允许使用strtol
。因此,您需要检查字符串中的每个字符。检查数字值的安全方法是使用 isdigit
库函数(还有 isodigit
和 isxdigit
函数分别用于检查八进制和十六进制数字),例如
while (*input && isdigit(*input))
input++;
(如果你甚至不被允许使用isdigit
、isodigit
或isxdigit
,那么就责备你的老师/教授让作业变得比实际需要的更难)。
如果您需要能够处理八进制或十六进制格式,那么它会变得更复杂一些。 C 约定是八进制格式有一个前导 0
数字,十六进制格式有一个前导 0x
。因此,如果第一个非空白字符是 0,则必须先检查下一个字符,然后才能知道要使用哪种非十进制格式。
基本大纲是
-
如果第一个非空白字符不是“-”、“+”、“0”或非零十进制数字,则这不是有效的整数字符串;
如果第一个非空白字符是'-',那么这是一个负值,否则我们假设一个正值;
如果第一个字符是“+”,那么这是一个正值;
如果第一个非空白和非符号字符是非零十进制数字,则输入为十进制格式,您将使用
isdigit
检查剩余字符;
如果第一个非空白和非符号字符是“0”,则输入为八进制或十六进制格式;
如果第一个非空白和非符号字符是“0”,下一个字符是从“0”到“7”的数字,则输入为八进制格式,您将使用isodigit
检查剩余的字符;
如果第一个非空白和非符号字符是0,第二个字符是x
或X
,则输入为十六进制格式,您将使用isxdigit
检查剩余字符;
如果任何剩余的字符不满足上面指定的检查函数,那么这不是一个有效的整数字符串。
【讨论】:
【参考方案4】:首先问问自己,你会如何曾经期望这段代码不返回一个整数:
int num;
scanf("%d",&num);
您将变量指定为整数类型,然后是 scanf
,但仅为整数 (%d
)。
此时它还可能包含什么?
【讨论】:
抱歉,人们似乎对这个答案赞不绝口,但我完全预料到你从算法中写的内容,但它没有用。我应该检查该值,使其永远不是非整数,并且您的解决方案不会削减它。我错过了什么吗?请解释一下。 @sombe:您缺少的是scanf("%d",&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", &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",&a);
和 a
的无效数字输入未初始化,q=(int)a;
未定义。代码应该在使用a
之前检查scanf("%f",&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",&x) != 1 )
循环是无限循环,如果stdin
关闭,scanf("%d",&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", &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", &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。以上是关于检查输入是不是是C中的整数类型的主要内容,如果未能解决你的问题,请参考以下文章