C 知识量:16 - 74 - 317
在实际应用中,用户不一定按照程序的指令行事,用户的输入与程序期望值不匹配时常发生,如果没有应对,就会导致程序运行失败。因此,在编程时要提高程序的可靠性,就必须事先预料一些可能的输入错误,并编写出能够检测和处理这些问题的程序。
下面借助一个较为复杂的示例来理解输入验证问题。示例程序的功能是计算特定范围内所有整数的平方和。限制数值的范围是-10000~10000。
#include <stdio.h> //声明整数类型输入验证函数 long get_long(void); //声明数值有效性验证函数 int bad_limits(long begin, long end, long low, long high); //声明整数平方和计算函数 double sum_squares(long a, long b); int main(void) { const long MIN = -10000L; //数值下限 const long MAX = 10000L; //数值上限 long start; //用户指定的范围最小值 long stop; //用户指定的范围最大值 double answer; printf("This program computes the sum of the squares " "of integer in a range(-10000~10000).\n" "Enter 0 for both limits to quit.\n"); printf("Please input lower limit:"); start = get_long(); printf("Please input upper limit:"); stop = get_long(); while (start != 0 || stop != 0) { if (bad_limits(start, stop, MIN, MAX)) printf("Please try again.\n"); else { answer = sum_squares(start, stop); printf("The sum of the squares of the integers " "from %ld to %ld is %g\n", start, stop, answer); } printf("Enter 0 for both limits to quit.\n"); printf("Please input lower limit:"); start = get_long(); printf("Please input upper limit:"); stop = get_long(); } printf("Done.\n"); system("pause"); return 0; } //整数类型输入验证函数定义 long get_long(void) { long input; char ch; while (scanf("%ld", &input) != 1) { while ((ch = getchar()) != '\n') putchar(ch); //处理错误输入 printf(" is not an integer.\nPlease input an integer value:"); } return input; } //整数平方和计算函数定义 double sum_squares(long a, long b) { double total = 0; long i; for (i = a; i <= b; i++) total += (double) i * (double) i; return total; } //数值有效性验证函数定义 int bad_limits(long begin, long end, long low, long high) { int not_good = 0; if (begin > end) { printf("%ld isn't smaller than %ld.\n", begin, end); not_good = 1; } if (begin < low || end < low) { printf("Values must be %ld or greater.\n", low); not_good = 1; } if (begin > high || end > high) { printf("Values must be %ld or less.\n", high); not_good = 1; } return not_good; }
运行结果为:
This program computes the sum of the squares of integer in a range(-10000~10000). Enter 0 for both limits to quit. Please input lower limit:low low is not an integer. Please input an integer value:a big number a big number is not an integer. Please input an integer value:5 Please input upper limit:11 The sum of the squares of the integers from 5 to 11 is 476 Enter 0 for both limits to quit. Please input lower limit:12 Please input upper limit:8 12 isn't smaller than 8. Please try again. Enter 0 for both limits to quit. Please input lower limit:0 Please input upper limit:0 Done.
以上示例中,实际计算部分占比很小,而数据验证部分占比却很大,因为数据的正确输入是计算正确的基础和前提。
上面的示例体现了模块化编程思想,使用了独立的函数(模块)来验证输入和管理显示。程序越大越复杂,使用模块化编程就越重要。
在以上代码中,main()函数是主函数,负责管理程序流,并为其他函数委派任务(调用其他函数)。
get_long()函数用于从用户获取值,并确保获得的是整数值。
bad_limits()函数用于检测值是否有效,验证值的范围和逻辑关系是否正确。
sum_squares()函数用于处理实际的计算,并向main()函数返回计算结果。
注意:在示例代码中,除了首先要导入头文件外,还要先声明要使用的自定义函数,即声明get_long()、bad_limits()和sum_squares()函数,后面虽然有它们的完整定义,但是程序自上而下编译,如果不事先声明,编译器就不认识它们,会报错。
在编写处理错误输入的代码时,应该明白C是如何处理输入的。例如:对于is 20 6.5,在我们眼中,这就是一个由字符、整数和浮点数组成的字符串。但对于C程序来说,这是一个字节流。第1个字节是字母i的字符编码,第2个字节是字母s的字符编码,第3个字节是空格字符的字符编码,第4个字节是数字2的字符编码,以此类推。因此,如果使用get_long()函数来处理这一行输入,因为第一个是非数字,所以整行输入都会被丢弃,包括其中的数字。
可以利用scanf()函数将输入流内容转换成数值。例如:对于45,如果使用%c转换说明,只会读取字符4,并储存到字符类型变量中;如果使用%s转换说明,会读取字符4和5,并存储为字符数组;如果使用%d转换说明,会读取字符4和5,并计算出对应的整数值45,存储到int类型变量中;如果使用%f转换说明,会读取字符4和5,并计算出对应的浮点值45.0,存储到float类型变量中。
总之,输入都由字符组成,C程序把输入作为传入的字节流,getchar()函数和scanf()函数把每个字符解释成一个字符编码。但是scanf()函数可以把输入转换成整数值或浮点数值,使用转换说明限制了可接受输入的字符类型。而getchar()函数和使用%c的scanf()函数可以接受所有的字符。
Copyright © 2017-Now pnotes.cn. All Rights Reserved.
编程学习笔记 保留所有权利
MARK:3.0.0.20240214.P35
From 2017.2.6