当前位置: 首页 > article >正文

算法竞赛中的输入输出框架

       例题:输入一些整数,求出它们的最小值、最大值和平均值(保留三位小数)。输入保证这些数都是不超过1000的整数。

        这个题目关键在于:整数的个数是不确定的。下面直接给出程序:

#include<stdio.h>
int main(){
	int x,n=0,min,max,s=0;
	while(scanf("%d",&x)==1){
		s=s+x;
		if(x>max){
			max=x;
		}
		if(x<min){
			min=x;
		}
		n++;
	}
	printf("%d %d %.3f\n",min,max,(double)s/n);
	return 0;
}

       这个程序中scanf有返回值,返回的是成功输入的变量个数,当输入结束时,scanf函数无法再次读取x,将返回0. 在Windows下,输入完毕后先按Enter键,再按Ctrl+Z键,最后在按Enter键即可结束输入。在Linux下,输入完毕后按Ctrl+D键即可结束输入。

       上面这个程序是错误的,变量在未赋值之前的值是不确定的。特别的,它不一定是0.只需要在使用之前赋初值就可以解决这个问题。一种方法是定义一个很大的常数,如INF=1000000000,然后让max=-INF,而min=INF,另一种方法是先读取第一个整数x,然后令max=min=x.这样的好处是避免了人为的“假想无穷大”值,程序更加优美。

       上面的程序并不是很方便,每次都要手动输入很多数。一个好的方法是用文件--把输入数据保存在文件中,输出数据也保存在文件中。这样,只要事先把输入数据保存在文件中,就不必每次重新输入了;数据输出在文件中也避免了“输出太多,一卷屏前面的就看不见了”这样的尴尬,运行结束后,慢慢浏览输出文件即可。

        使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入以下两条语句:

freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);

      上述语句将使得scanf从文件input.txt读入,printf写入文件output.txt。不只是scanf和printf,所有读键盘输入、写屏幕输出的函数都将改用文件。尽管这样做很方便,但并不是所有算法竞赛都允许程序读写文件。甚至有的算法竞赛允许访问文件,但不允许用freopen这样的重定向方式读写文件。参赛之前仔细阅读文件读写的相关规定:是标准输入输出(也称标准I/O,即直接读键盘,写屏幕),还是文件输入输出?如果是文件输入输出,是否禁止用重定向方式访问文件?同时注意不要弄错大小写,不要弄错文件名,不要使用绝对路径或相对路径。

        有一种方法可以在本机测试时用文件重定向,但一旦提交比赛,就自动“删除”重定向语句。

#define LOCAL
#include<stdio.h>
#define INF 1000000000
int main(){
	#ifdef LOCAL
	freopen("data.in","r",stdin);
	freopen("data.out","w",stdout);
	#endif
	int x,n=0,min=INF,max=-INF,s=0;
	while(scanf("%d",&x)==1){
		s=s+x;
		if(x>max){
			max=x;
		}
		if(x<min){
			min=x;
		}
		/* 
		printf("x = %d, min = %d. max = %d\n, x, min, max);
		*/
		n++;
	}
	printf("%d %d %.3f\n",min,max,(double)s/n);
	return 0;
} 

        这是一份典型的比赛代码,包含了几个特别之处:

       1.重定向的部分被写在了#ifdef和#endif中。其含义是:只有定义了符号LOCAL,才编译两条freopen语句。

       2.输出中间结果的printf语句写在了注释中,它在最后版本的程序中不应该出现,可以在发现了bug后,输出中间信息。 

       上面的代码在程序首部就定义了符号LOCAL,因此在本机测试时使用重定向方式读写文件。如果比赛要求读写标准输入输出,只需要在提交之前删除#define LOCAL即可。

        如果比赛要求用文件输入输出,但禁止用重定向的方式,使用的程序如下

#include<stdio.h>
#define INF 1000000000
int main(){
	FILE *fin,*fout;
	fin = fopen("data.in","rb");
	fout = fopen("data.out","wb");
	int x,n=0,min,max,s=0;
	min=INF;
	max=-INF;
	while(fscanf(fin,"%d",&x)==1){
		s+=x;
		if(x<min){
			min=x;
			
		}
		if(x>max){
			max=x;
			
		}
		n++;
		
	}
	fprintf(fout,"%d %d %.3f\n",min,max,(double)s/n);
	fclose(fin);
	fclose(fout);
	return 0;
}

       上面这个代码很直观,先声明变量fin和fout,把scanf改为fscanf,第一个参数为fin;把printf改为fprintf,第一个参数为fout,最后执行fclose,关闭两个文件。

       重定向和fopen两种方法各有优劣,重定向的方法写起来简单,但是不能同时读写文件和标准输入输出;fopen的写法稍显繁琐,但是灵活性比较大(例如,可以反复打开并读写文件)。如果想把fopen版的程序改成读写标准输入输出,只需赋值“fin=stdin;fout=stdout"即可,不要调用fopen和fclose。


http://www.kler.cn/a/154104.html

相关文章:

  • 【gitlab】gitlabrunner部署
  • 若依权限控制
  • 【UGUI】背包的交互01(道具信息跟随鼠标+道具信息面板显示)
  • leetcode 面试150之 Z 字形变换
  • Spring Events在大型项目中的最佳实践
  • 怎样在软件设计中选择使用GOF设计模式
  • Java研学-IO流(三)
  • 熬夜会秃头——beta冲刺Day2
  • 分享83个节日PPT,总有一款适合您
  • System.out.println隐藏字符串
  • Python中用于机器学习的Lazy Predict库
  • 大学里学编程,为什么这么难?
  • Windows启动nacos操作文档
  • 2017年五一杯数学建模A题公交车排班问题解题全过程文档及程序
  • linux设置权限_setfacl_getfacl
  • HT81298 集成免滤波器调制D类音频功放
  • FLASK博客系列7——我要插入数据库
  • 服务器基础知识
  • H5 uniapp 接入wx sdk
  • Day12 qt QMianWindow,资源文件,对话框,布局方式,常用ui控件
  • Effective C++(二):对象的初始化
  • 植物单细胞基础工程之标记基因数据库
  • 号称要做人民货币的Spacemesh,有何新兴叙事?
  • 记录 | photoshop移动选区
  • 怎么让百度快速收录,百度SEO收录工具
  • 【干货】接口公共方法(字典表查询)