c - 提示用户输入整数值并检查有效输入的函数
问题描述
我目前被困在我需要做的任务的一小部分。任务的一项要求是
“调用一个函数,提示用户输入二次方程的系数 a、b 和 c 的每个值,并返回输入的值,并对有效输入进行错误检查(scanf 返回一个值)。”
我不知道该怎么做。我可以很容易地提示用户输入,我可以检查它是否是有效的输入,但我不知道如何把它变成一个函数。我目前的代码是:
{
if (isalpha(a))
{
printf("INPUT ERROR!\n");
printf("Enter a value for a: ");
scanf("%d", &a);
}
} //this is how I would normally check the input
int main(void) //start of main() function definition
{
int a, b, c, n, D; //declares integer variables a, b, c, n, and D
float root1, root2; //declares float variables root1 and root2
do //do while loop starts here
{
printf("Enter a value for a: "); //prompts user to input integer for variable 'a'
scanf("%d", &a); //reads an integer from the keyboard and stores in the variable 'a'
printf("%d\n", a); //returns value of integer that was input for variable 'a'
printf("Enter a value for b: "); //prompts user to input integer for variable 'b'
scanf("%d", &b); //reads an integer from the keyboard and stores in the variable 'b'
printf("%d\n", b); //returns value of integer that was input for variable 'b'
printf("Enter a value for c: "); //prompts user to input integer for variable 'c'
scanf("%d", &c); //reads an integer from the keyboard and stores in the variable 'c'
printf("%d\n", c); //returns value of integer that was input for variable 'c'
...}
抱歉任何格式错误,但这基本上是我坚持的程序的一部分。
我的问题是,如何将第一个函数与 do/while 循环中的所有内容结合起来,以创建一个可以调用 3 次的大函数?
我不知道如何使用函数来切换 a for b 和 c 的所有实例,因为我以前从未真正使用过这样的函数。
解决方案
提示用户输入整数值并检查有效输入的函数
如果用户只逐行输入有效的整数文本,那么代码很简单:
// Overly idealized case
fputs(prompt, stdout);
char buf[50];
fgets(buf, sizeof buf, stdin);
int i = atoi(buf);
但是用户是好,坏和丑陋的,**它发生了。如果代码想要读取一行,将其解析为 in-rangeint
并检测大量问题,下面是审查许多虚假和恶意输入的典型问题的代码。
我特别感兴趣的是检测过长的输入是恶意的,并且作为针对黑客的谨慎设计而无效。int
如下所示,几乎没有理由允许超过 20 个字符的 32 位有效输入。这种理性值得更深入的解释。
- 文件结束
- 输入流错误
- 溢出
- 没有领先的数字测试
- 尾随非数字文本
- 线路过长
首先读取一行fgets()
输入,然后int
应用各种验证测试。如果fgets()
没有读取整行,则读取其余部分。
#include <limits.h>
#include <ctype.h>
// Max number of `char` to print an `int` is about log10(int_bit_width)
// https://stackoverflow.com/a/44028031/2410359
#define LOG10_2_N 28
#define LOG10_2_D 93
#define INT_DEC_TEXT (1 /*sign*/ + (CHAR_BIT*sizeof(int)-1)*LOG10_2_N/LOG10_2_D + 1)
// Read a line and parse an integer
// Return:
// 1: Success
// 0: Failure
// EOF: End-of-file or stream input error
int my_get_int(int *i) {
// Make room for twice the expected need. This allows for some
// leading/trailing spaces, leading zeros, etc.
// int \n \0
char buf[(INT_DEC_TEXT + 1 + 1) * 2];
if (fgets(buf, sizeof buf, stdin) == NULL) {
*i = 0;
return EOF; // Input is either at end-of-file or a rare input error.
}
int success = 1;
char *endptr;
errno = 0;
long value = strtol(buf, &endptr, 10);
// When `int` is narrower than `long`, add these tests
#if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
if (value < INT_MIN) {
value = INT_MIN;
errno = ERANGE;
} else if (value > INT_MAX) {
value = INT_MAX;
errno = ERANGE;
}
#endif
*i = (int) value;
if (errno == ERANGE) {
success = 0; // Overflow
}
if (buf == endptr) {
success = 0; // No conversion
}
// Tolerate trailing white-space
// Proper use of `is...()` obliges a `char` get converted to `unsigned char`.
while (isspace((unsigned char ) *endptr)) {
endptr++;
}
// Check for trailing non-white-space
if (*endptr) {
success = 0; // Extra junk
while (*endptr) { // quietly get rest of buffer
endptr++;
}
}
// Was the entire line read?
// Was the null character at the buffer end and the prior wasn't \n?
const size_t last_index = sizeof buf / sizeof buf[0] - 1;
if (endptr == &buf[last_index] && buf[last_index - 1] != '\n') {
// Input is hostile as it is excessively long.
success = 0; // Line too long
// Consume text up to end-of-line
int ch;
while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
;
}
}
return success;
}
示例使用
puts("Enter a value for a: ", stdout);
fflush(stdout); // Insure output is seen before input.
int a;
if (my_get_int(&a) == 1) {
printf("a:%d\n", a);
}
推荐阅读
- r - R:如何将多边形的直线和线段与极坐标结合起来?
- css - 使用 sass 算术运算符时出现 W3c 验证错误
- jquery - 我想从动态创建的 span 元素中使用 jquery 获取 data-id 和 data-test 的值
- ssis - 在 SSIS 中 Union-all 后记录数下降
- docker - 在 Jenkins 上执行 shell 脚本时作业随机失败
- typescript - 无法将函数返回的布尔值存储在打字稿的变量中
- javascript - 从流中获取第一个定义的值并在 RxJS 中取消订阅的最佳方法是什么?
- html - 如何将两个表与不同的列对齐
- ios - 将数据添加到数据库后如何从 Core Data 中获取数据
- vb.net - 参数 productID 没有默认值