题目:数据统计 (p27-32)
输入一些整数,求出它们的最小值、最大值和平均值(保留三位小数),输入保证这些数都是不超过1000的整数
样例输入
2 8 3 5 1 7 3 6
样例输出
1 8 4.375
先给代码(有bug)
#include
int main()
{
int x,n=0,min,max,s=0;
while(scanf("%d",&x)==1)
{
s+=x;
if(xmax)
max=x;
n++;
}
printf("%d %d %.3f\n",min,max,(double)s/n);
return 0;
}
1.scanf()函数返回成功输入的变量个数,当输入结束时,scanf函数无法读取变量,将返回零
2.在Windows下,输入完毕后先按Enter键,再按Ctrl+Z键,最后按Enter键即可结束输入
在Linux下,输入完毕后按Ctrl+D键即可结束输入
3.但是输出结果却是不确定的,通过输出中间结果的方法,很容易发现变量max,min一开始未初始化
书上解决方法:可以用一个很小的值来初始化max;用一个很大的值来初始化min;
本题中可以使INF=1000;max=-INF;min=INF;
自己想法:min,max都用第一个读取的数来初始化
代码如下:
#include
int main()
{
int x,n=0,min,max,s=0;
while(scanf("%d",&x)==1)
{
s+=x;
min=x;
max=x;
n++; //min,max都用第一个读取的数来初始化
while(scanf("%d",&x)==1)
{
s+=x;
if(xmax)
max=x;
n++;
}
break;
}
printf("%d %d %.3f\n",min,max,(double)s/n);
return 0;
}
4.本题是手动输入,略显麻烦,可以采取文件输入方式
使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入两条语句:
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
ps:在算法竞赛中,首先要弄清是标准输入输出,还是文件输入输出?如果是文件输入输出,是否禁止用重定向方式访问文件
另外也要严格遵守文件名规定,包括程序文件名和输入输出文件名。不要弄错大小写,不要拼错文件名,不要使用绝对路径或相对路径
5.当然,即使比赛要求是标准输入输出,也可以使用文件输入输出,可以避免繁琐的手动输入输出,但是最后提交时可以用条件编译指令将重定向语句删掉
代码如下:
#include
#define LOCAL //在标准输入输出比赛中,最后要记得注释掉这一行
#define INF 1000
int main()
{
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
int x,n=0,min=INF,max=-INF,s=0;
while(scanf("%d",&x)==1)
{
s+=x;
if(xmax)
max=x;
n++;
}
printf("%d %d %.3f\n",min,max,(double)s/n);
return 0;
}
6.如果比赛要求用文件输入输出,但禁止用重定向的方式,代码如下:
#include
#define INF 1000
int main()
{
FILE *fin,*fout;
fin=fopen("data.in","rb");
fout=fopen("data.out","wb");
int x,n=0,min=INF,max=-INF,s=0;
while(fscanf(fin,"%d",&x)==1)
{
s+=x;
if(xmax)
max=x;
n++;
}
fprintf(fout,"%d %d %.3f\n",min,max,(double)s/n);
fclose(fin);
fclose(fout);
return 0;
}
ps:重定向和fopen两种方法各有优劣
重定向简单自然,但是不能同时读写文件和标准输入输出
fopen的写法较为繁琐,但是灵活性比较大,例如可以反复打开并读写文件,也可以通过赋值“fin=stdin;fout=stout”并删掉调用fopen和fclose语句来改成标准输入输出
题目:数据统计|| (p32-34)
输入一些整数,求出它们的最小值、最大值和平均值(保留三位小数),输入保证这些数都是不超过1000的整数
输入包含多组数据,每组数据第一行是整数个数n,第二行是n个整数。n=0为输入结束标志,程序应当忽略这组数据。相邻两组数据之间应输出一个空行
样例输入
8
2 8 3 5 1 7 3 6
4
-4 6 10 0
0
样例输出
Case 1:1 8 4.375
Case 2:-4 10 3.000
老规矩,先贴代码(有bug):
#include
#define INF 1000
int main()
{
int x,n=0,min=INF,max=-INF,s=0,kase=0;
while(scanf("%d",&n)==1&&n)
{
int s=0;
for(int i=0;imax)
max=x;
}
if(kase) printf("\n"); //为了符合题目“相邻两组数据之间应输出一个空行”这一要求
printf("Case %d: %d %d %.3f\n",++kase,min,max,(double)s/n);
}
return 0;
}
1.程序之所以仍然判断scanf的返回值,是为了提高代码的鲁棒性,即为了防止比赛数据有瑕疵
3.当在样例输入的最后增加第三组数据:1 0
输出为Case 3:-4 10 0.000
很明显,这是上一组的数据结果
由此可见:在多数据的题目中,一个常见错误是:在计算完上一组数据后,某些重复使用的变量没有重置,从而影响到下一组数据的结果