如何使用 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);
}
此方法存在一个问题,即如果输入的字符串长度比分配给 input
的长度长,则无法处理。
<强>3。如果使用指针定义字符串会怎样?
我关心的是通过指针定义input
,例如char *input;
。但是,一旦我执行 gets(input)
(或 scanf("%s", input)
),它就会引发运行时错误。
那么使用 scanf
或 gets
从控制台窗口检索整数值的正确方法是什么?
最佳答案
答案取决于您所说的安全到底是什么意思。安全。如果您想捕获任何可能的输入错误,唯一的选择是使用 strtol() 系列的函数,它甚至允许进行范围检查。在我的beginners' guide away from scanf()
,我正在描述它的用途。
这是适合您在此处尝试的代码,并带有注释:
#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;
}
关于C 整数安全输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50096953/