问题在于我不能使用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)
但是这些都没有起作用。
有什么想法吗?
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");
scanf
正在读取一个数字并检测到一个非数字字符时,它只会停在那里并将其留给流(在这种情况下,只会简单地“返回”2)。 - eq-scanf("%d%c", &num, &term)
返回>= 1
就足以知道是否输入了一个int
。换句话说,输入可能只有1
,2
,3
,文件结束符
。 - chux - Reinstate Monicachar 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;
}
}
}
gets()
函数。 - Greg Hewgillsscanf(s, "%d", num);
,它将把它转换为整数。 - user470379使用 %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
,那么就应该责骂你的老师或教授,因为这让任务变得比实际需要的更加困难。)0
开头,十六进制格式则以前导数字 0x
开头。因此,如果第一个非空白字符是 0,则必须检查下一个字符才能确定要使用哪种非十进制格式。isdigit
检查剩余字符;isodigit
检查剩余字符;x
或 X
,则输入是以十六进制格式表示的,您将使用 isxdigit
检查剩余字符;首先请问您如何预料这段代码不返回整数:
int num;
scanf("%d",&num);
scanf
函数,但是只为整数(%d
)赋值。scanf("%d",&num)
只会根据定义将整数值存储到 num
中;无论这个值与输入字符串是否有任何关系都是一个未解决的问题。如果你输入了一些带有前导数字的内容(比如 "12efg"),scanf
会读取、转换和赋值前导的 "12",而将 "efg" 留在输入流中。如果输入字符串不以数字开头(例如 "ab123"),则不会读取输入字符串的任何部分,而 num
将包含调用之前的值(仍然是一个整数)。 - John Bodeint
使用陷阱了。 - chux - Reinstate Monica#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");
}
我想这个更加用户友好:
#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 )
loop is infinite loop should stdin
get closed as scanf("%d",&x)
will forever return EOF
. As well while ( getchar() != '\n' )
- chux - Reinstate Monica我使用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
值是不足够的。 - chux - Reinstate Monica#include <cs50.h>
这里有一个 get_int 函数,你可以直接用它来初始化变量:
int a = get_int("Your number is: ");
#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)
的返回值。 - chux - Reinstate Monica试一试...
#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)
的返回值。 - chux - Reinstate Monica
atoi()
,因为这个想法是你通过遍历字符并检查它们是否在0-9范围内来手动进行检查。因此,很可能也不应该使用scanf()
。 - Peter - Reinstate Monica