C整数安全输入
如何使用C整数安全输入,c,integer,scanf,gets,C,Integer,Scanf,Gets,如何使用scanf或gets获得整数(尤其是正数)的安全输入?我尝试了几种解决方案,每种解决方案都有一些问题 1。使用getchar()删除字符串输入 int safeInput() { int input; scanf("%d", &input); while(getchar() != '\n'); return input; } 此方法有效地处理字符串输入,但是,如果输入了3a等字符串,则input的值变为3,这不是真正的异常句柄 2。以字符串形式检
scanf
或gets
获得整数(尤其是正数)的安全输入?我尝试了几种解决方案,每种解决方案都有一些问题
1。使用getchar()
删除字符串输入
int safeInput() {
int input;
scanf("%d", &input);
while(getchar() != '\n');
return input;
}
此方法有效地处理字符串输入,但是,如果输入了3a
等字符串,则input
的值变为3
,这不是真正的异常句柄
2。以字符串形式检索输入,然后转换为整数值。
int safeInput() {
char[200] input, safe_input;
gets(input);
// I know about the security issue about gets - but it's not the point.
int i = 0;
while (1) {
if (input[i] >= 48 && input[i] <= 57) safe_input[i] = input[i];
else break;
i++;
}
return atoi(safe_input);
}
int-safeInput(){
字符[200]输入,安全输入;
获取(输入);
//我知道gets的安全问题,但这不是重点。
int i=0;
而(1){
如果(输入[i]>=48&&input[i]首先,如果你想要一个安全的输入,不要使用get
。当你可以使用fgets
时,说你知道这些问题并不是一个真正的借口。接下来,诀窍是尝试读取int后面的非空字符:如果你找不到任何字符,那么int后面就没有任何字符了
int safeInput(int *input) { // the return value is the indicator of failed read
int c;
char dummy[2]; // never forget the terminating null!
if (scanf("%d%1s", input, dummy) == 1) return 1;
// in case of error, skip anything up to end of line or end of file
while (((c = fgetc(stdin)) != '\n') && (c != EOF));
return 0;
}
这里的优点是,当scanf
返回1时,%1s
已经吃掉了行末尾的任何东西,包括终止的“n”
。但这有一个主要缺点:scanf
只会在流的末尾或在读取一个额外的(非空)后结束字符。因此,Felix Palmen的答案使用起来更简单、更安全。首先,如果你想要一个安全的输入,不要使用gets
。当你可以使用fgets
时,说你知道这些问题并不是一个真正的借口。接下来,诀窍是尝试读取int后面的一个非空字符:如果你没有找到one,那么在这行的int之后没有任何内容
int safeInput(int *input) { // the return value is the indicator of failed read
int c;
char dummy[2]; // never forget the terminating null!
if (scanf("%d%1s", input, dummy) == 1) return 1;
// in case of error, skip anything up to end of line or end of file
while (((c = fgetc(stdin)) != '\n') && (c != EOF));
return 0;
}
这里的优点是,当scanf
返回1时,%1s
已经吃掉了行末尾的任何东西,包括终止的“n”
。但这有一个主要缺点:scanf
只会在流的末尾或在读取一个额外的(非空)后结束字符。因此,Felix Palmen的答案使用起来更简单、更安全。答案取决于您所说的“安全”的确切含义。如果您想捕获任何可能的输入错误,您唯一的选择就是使用strtol()
系列的函数,它甚至允许范围检查。在我的文章中,我将介绍它的用法
以下是与您在此处尝试的内容相适应的代码,并附有注释:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
// return success as boolean (0, 1), on success write result through *number:
int safeInput(int *number)
{
long a;
char buf[1024]; // use 1KiB just to be sure
if (!fgets(buf, 1024, stdin))
{
// reading input failed:
return 0;
}
// have some input, convert it to integer:
char *endptr;
errno = 0; // reset error number
a = strtol(buf, &endptr, 10);
if (errno == ERANGE)
{
// out of range for a long
return 0;
}
if (endptr == buf)
{
// no character was read
return 0;
}
if (*endptr && *endptr != '\n')
{
// *endptr is neither end of string nor newline,
// so we didn't convert the *whole* input
return 0;
}
if (a > INT_MAX || a < INT_MIN)
{
// result will not fit in an int
return 0;
}
// write result through the pointer passed
*number = (int) a;
return 1;
}
#包括
#包括
#包括
#包括
//将成功返回为布尔值(0,1),成功时通过*号写入结果:
整数安全输入(整数*数字)
{
长a;
char buf[1024];//使用1KiB只是为了确保
如果(!fgets(buf,1024,stdin))
{
//读取输入失败:
返回0;
}
//有一些输入,将其转换为整数:
char*endptr;
errno=0;//重置错误号
a=标准温度(buf和endptr,10);
if(errno==ERANGE)
{
//长时间在射程之外
返回0;
}
如果(endptr==buf)
{
//没有读到任何字符
返回0;
}
如果(*endptr&&*endptr!='\n')
{
//*endptr既不是字符串的结尾,也不是换行符,
//所以我们没有转换整个输入
返回0;
}
如果(a>INT_MAX | a
答案取决于您所说的“安全”的确切含义。如果您想捕获任何可能的输入错误,您唯一的选择是使用strtol()
系列的函数,它甚至允许进行范围检查。在我的文章中,我描述了它的用法
以下是与您在此处尝试的内容相适应的代码,并附有注释:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
// return success as boolean (0, 1), on success write result through *number:
int safeInput(int *number)
{
long a;
char buf[1024]; // use 1KiB just to be sure
if (!fgets(buf, 1024, stdin))
{
// reading input failed:
return 0;
}
// have some input, convert it to integer:
char *endptr;
errno = 0; // reset error number
a = strtol(buf, &endptr, 10);
if (errno == ERANGE)
{
// out of range for a long
return 0;
}
if (endptr == buf)
{
// no character was read
return 0;
}
if (*endptr && *endptr != '\n')
{
// *endptr is neither end of string nor newline,
// so we didn't convert the *whole* input
return 0;
}
if (a > INT_MAX || a < INT_MIN)
{
// result will not fit in an int
return 0;
}
// write result through the pointer passed
*number = (int) a;
return 1;
}
#包括
#包括
#包括
#包括
//将成功返回为布尔值(0,1),成功时通过*号写入结果:
整数安全输入(整数*数字)
{
长a;
char buf[1024];//使用1KiB只是为了确保
如果(!fgets(buf,1024,stdin))
{
//读取输入失败:
返回0;
}
//有一些输入,将其转换为整数:
char*endptr;
errno=0;//重置错误号
a=标准温度(buf和endptr,10);
if(errno==ERANGE)
{
//长时间在射程之外
返回0;
}
如果(endptr==buf)
{
//没有读到任何字符
返回0;
}
如果(*endptr&&*endptr!='\n')
{
//*endptr既不是字符串的结尾,也不是换行符,
//所以我们没有转换整个输入
返回0;
}
如果(a>INT_MAX | a
不要使用gets
。关于第三种方法:char*input;
只是声明一个指针,但是input
没有指向任何地方,它没有初始化。阅读C教科书中关于指针的章节。不要使用gets
。改用fgets
。那么方法2有什么问题吗?1.逐行阅读(fgets()
),2.解析输入(strtol()
和朋友)。另请参见我的。@GreenRoof well没有NUL终止符完全是错误的。是的,如果使用get
,输入溢出是一个问题。如果使用fgets
,则不是问题。不要使用get
。关于第三种方法:char*input;
只是声明了一个指针,但input
没有指向任何地方,它不是我初始化。阅读C教科书中有关指针的章节。在上,不要使用get
。而是使用fgets
。那么方法2有什么问题吗?1.逐行阅读(fgets()
),2.解析输入(strtol()
和friends).另请看我的。@GreenRoof没有NUL终结者是完全错误的。是的,inpu