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

本文参考自:《算法竞赛入门经典(第2版)》(刘汝佳编),侵删。

例题2-5 数据统计

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

  • 在标准输入输出中,不知道循环次数和循环条件时:

    添加while(scanf("%d",&x)==1)的语句,在Windows下,输入完毕后先按Enter,再按Ctrl+Z,再按Enter,即可结束输入。

  • 上面的程序并不是很方便:每次测试都要手动输入许多数。尽管可以用前面讲的管道的方法,但数据只是保存在命令行中,仍然不够方便。

    一个好的方法是用文件把输入数据保存在文件中,输出数据也保存在文件中。这样,只要事先把输入数据保存在文件中,就不必每次重新输入了;数据输出在文件中也避免了“输出太多,一卷屏前面的就看不见了”这样的尴尬,运行结束后,慢慢浏览输出文件即可。如果有标准答案文件,还可以进行文件比较1,而无须编程人员逐个检查输出是否正确。事实上,几乎所有算法竞赛的输入数据和标准答案都是保存在文件中的。
    使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入以下两条语句:

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

    比赛中一个普适的原则是:详细阅读比赛规定,并严格遵守。例如:输入输出文件名和程序名往往都有着严格规定,不要弄错大小写,不要拼错文件名,不要使用绝对路径或相对路径。

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

    #define LOCAL
    #include<stdio.h>
    #define INF 10000000000
    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+=x;
            if(x<min)min=x;
            if(x>max)max=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;
    }
    

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

    • 重定向的部分被写在了#ifdef和#endif中。其含义是:只有定义了符号LOCAL,才编译两条 freopen语句。
    • 输出中间结果的 printf写在了注释中——它在最后版本的程序中不应该出现,但是又舍不得删除它(万一发现了新的bug,需要再次用它输出中间信息)。将其注释的好处是:一旦需要时,把注释符去掉即可。

    上面的代码在程序首部就定义了符号 LOCAL,因此在本机测试时使用重定向方式读写文件。如果比赛要求读写标准输入输出,只需在提交之前删除#define LOCAL即可。一个更好的方法是在编译选项而不是程序里定义这个 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=INF,max=-INF,s=0;
    while(fscanf("%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;
}

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


  1. 在Windows中可以使用fc命令,在Linux上可以使用diff命令。 ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值