仅在C中输入验证整数
我的节目是马里奥金字塔。我似乎无法在C中完成输入验证。如果有人能解释输入验证和出错的地方。谢谢这是我的密码副本仅在C中输入验证整数,c,cs50,C,Cs50,我的节目是马里奥金字塔。我似乎无法在C中完成输入验证。如果有人能解释输入验证和出错的地方。谢谢这是我的密码副本 // Prompt user till input is 0-23 do { printf("Welcome to Mario Pyramid Builder! Enter a number from 0 - 23: "); scanf("%d", &height); if(height >= 0 && height <= 2
// Prompt user till input is 0-23
do
{
printf("Welcome to Mario Pyramid Builder! Enter a number from 0 - 23: ");
scanf("%d", &height);
if(height >= 0 && height <= 23)
{
break;
}
else
{
printf("Wrong Input! Try Again.");
continue;
}
}
while ((height < 0) || (height > 23));
//提示用户直到输入为0-23
做
{
printf(“欢迎使用马里奥金字塔生成器!输入一个0-23:”)之间的数字;
扫描频率(“%d”和高度);
如果(高度>=0和高度23));
scanf
不会删除额外的字符,它只提取您在格式说明符中输入的字符,其他字符(如\n)保留在缓冲区中。为避免scanf复杂化,请使用fgets从键盘读取一行,然后使用sscanf()
提取整数(或仅使用普通的atoi()
)
。。。
字符缓冲区[128];
如果(fgets(buffer,sizeof(buffer,stdin)!=NULL)
{
如果(sscanf(缓冲区、%d、&H)==1)
{
如果(height>=0&&heightC中的输入验证是一件麻烦事,需要您做一些工作。不要依靠scanf
来为您做艰苦的工作,因为它不会。如果您输入像12dw
这样的输入,使用%d
转换说明符的scanf
将成功读取、转换和分配12
到您的目标,同时在输入流中保留dw
,以干扰下一次读取
理想情况下,对于交互式输入,您应该将输入读入文本缓冲区,然后自己转换为目标类型。这将有助于防止出现上述情况,并有助于防止出现令人讨厌的长输入试图利用溢出漏洞或类似情况
因此,从输入缓冲区的固定大小数组char
开始:
#define MAX_INPUT_LENGTH 13 // enough for 32-bit decimal integer, plus sign
char input[MAX_INPUT_LENGTH+1]; // +1 for string terminator
您将使用fgets
读取输入:
if ( !fgets( input, sizeof input, stdin ) )
{
// error on input
}
else
{
// process input
}
您要进行的下一项检查是查看输入缓冲区中是否有换行符-如果没有,则用户输入的值太大,无法表示为本机整数类型。如果是这种情况,则您希望放弃当前输入,然后读取并放弃直到下一个换行符的所有内容:
char *newline = strchr( input, '\n' );
if ( !newline )
{
while ( getchar() != '\n' ) // read and discard everything up to the next newline
;
}
else
{
// convert input
}
现在,您可以将输入从文本转换为整数了。使用strtol
库函数(原型包括stdlib.h
),因为它允许检查输入中是否有任何非数字、非空白字符
char *chk;
height = (int) strtol( input, &chk, 0 );
if ( !isspace( *chk ) || *chk != 0 ) // include ctype.h for isspace
{
// conversion was unsuccessful, bad input
}
else
{
// check range
}
把所有这些放在一起,你会得到如下结果:
#include <stdlib.h>
#include <ctype.h>
...
#define MAX_INPUT_LENGTH 13
...
int height;
int done = 0;
printf( "Welcome to Mario Pyramid Builder!\n" );
do
{
char input[MAX_INPUT_LENGTH+1];
height = -1; // initialize height to an invalid value
printf( "Enter a number from 0 to 23: " );
if ( !fgets( input, sizeof input, stdin ) )
{
fprintf( stderr, "Error on input, try again!\n" );
}
else
{
//
// make sure input wasn't too long for the input buffer by
// checking for a newline.
//
char *newline = strchr( input, '\n' );
if ( !*newline )
{
while ( getchar() != '\n' )
;
fprintf( stderr, "Input too long, try again!\n" );
}
else
{
//
// Convert text in input buffer to an integer. chk will point
// to the first character in input that is not a decimal digit.
// If that character is not 0 or whitespace, then we have
// bad (non-numeric) input.
//
char *chk;
height = strtol( input, &chk, 10 );
if ( !isspace( *chk ) || *chk != 0 )
{
fprintf( stderr, "Non-numeric input detected, try again!\n" );
}
else
{
//
// if height is between 0 and 23, done will be set to true,
// and we'll exit the loop.
//
done = height >= 0 && height <= 23;
}
}
}
} while ( !done );
#包括
#包括
...
#定义最大输入长度13
...
内部高度;
int done=0;
printf(“欢迎来到马里奥金字塔生成器!\n”);
做
{
字符输入[最大输入长度+1];
高度=-1;//将高度初始化为无效值
printf(“输入一个从0到23的数字:”);
如果(!fgets(输入,输入大小,标准输入))
{
fprintf(stderr,“输入错误,重试!\n”);
}
其他的
{
//
//确保输入对于输入缓冲区来说不是太长
//正在检查换行符。
//
char*newline=strchr(输入“\n”);
如果(!*换行符)
{
而(getchar()!='\n')
;
fprintf(stderr,“输入太长,请重试!\n”);
}
其他的
{
//
//将输入缓冲区中的文本转换为整数。chk将指向
//输入中非十进制数字的第一个字符。
//如果该字符不是0或空白,则
//输入错误(非数字)。
//
char*chk;
高度=strtol(输入和chk,10);
如果(!isspace(*chk)|*chk!=0)
{
fprintf(stderr,“检测到非数字输入,请重试!\n”);
}
其他的
{
//
//如果高度介于0和23之间,则“完成”将设置为true,
//我们将退出循环。
//
done=height>=0&&height代替1980年代风格的交互式输入,为什么不使用argv
?scanf
返回成功转换的次数,在您的情况下应该是1。如果返回值不是1,则用户输入垃圾,您需要读取换行符之前的所有字符,然后重试。另外,由于循环将中断
当输入有效时,您不需要do/while
。一个简单的while(1)
就是所需的一切。@tadman CS50…@AnttiHaapala也许他们应该更新它以使用本世纪的约定。还有和朋友们,当你说!=1时,它们比If语句中的atoi
有更好的错误检查。我能做类似的事情吗?而且当我运行它时,它会拒绝有效信息。!=(height>=0&&height@ConnorHutch我在原始答案中省略了细节,现在我编辑了答案以使其更清晰。回答很好,但您可以重新启动fgets()
在非整数输入的情况下。@chqrlie oops typo,感谢您指出这一点。关于重新启动,我认为这将在他的while循环中运行,因此,如果错误,可以继续。
#include <stdlib.h>
#include <ctype.h>
...
#define MAX_INPUT_LENGTH 13
...
int height;
int done = 0;
printf( "Welcome to Mario Pyramid Builder!\n" );
do
{
char input[MAX_INPUT_LENGTH+1];
height = -1; // initialize height to an invalid value
printf( "Enter a number from 0 to 23: " );
if ( !fgets( input, sizeof input, stdin ) )
{
fprintf( stderr, "Error on input, try again!\n" );
}
else
{
//
// make sure input wasn't too long for the input buffer by
// checking for a newline.
//
char *newline = strchr( input, '\n' );
if ( !*newline )
{
while ( getchar() != '\n' )
;
fprintf( stderr, "Input too long, try again!\n" );
}
else
{
//
// Convert text in input buffer to an integer. chk will point
// to the first character in input that is not a decimal digit.
// If that character is not 0 or whitespace, then we have
// bad (non-numeric) input.
//
char *chk;
height = strtol( input, &chk, 10 );
if ( !isspace( *chk ) || *chk != 0 )
{
fprintf( stderr, "Non-numeric input detected, try again!\n" );
}
else
{
//
// if height is between 0 and 23, done will be set to true,
// and we'll exit the loop.
//
done = height >= 0 && height <= 23;
}
}
}
} while ( !done );