提示2-15:在Windows下,输入完毕后先按Enter键,再按Ctrl+Z键,最后再按Enter键,即可结束输入。在Linux下,输入完毕后按Ctrl+D键即可结束输入。
使用文件的两种方式包括:freopen和fopen。
freopen方式
使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入以下两条语句:
freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
它使得scanf从文件input.txt读入,printf写入文件output.txt。事实上,不只是scanf和printf,所有读键盘输入、写屏幕输出的函数都将改用文件。尽管这样做很方便,并不是所有算法竞赛都允许你用程序读写文件。甚至有的竞赛允许访问文件,但不允许你用freopen这样的重定向方式读写文件。
有一种方法可以再本机测试时用文件重定向,但一旦提交到比赛,就自动“删除”重定向语句。代码如下:
程序2-8 数据统计(重定向版)
#define LOCAL #include <stdio.h> #define INF 1000000000 int main() { #ifdef LOCAL freopen("data.in", "r", stdin); freopen("data.out", "w", stdout); #endif // LOCAL int x, n = 0, min = INF, max = -INF, s = 0; while (scanf("%d", &x) != EOF) { s += x; if (x < min) min = x; if (x > max) max = x; n ++; } printf("%d %d %.3lf\n", min, max, (double)s/n); return 0; }
重定向的部分被卸载了#ifdef和#endif中。它的含义是:只有定义了LOCAL,才编译两条freopen语句。
上面的代码在程序首部就定义了LOCAL,因此在本机测试时使用重定向方式读写文件。如果比赛要求读写标准输入输出,只需在提交之前删除#define LOCAL即可。一个更好的方法是在编译选项而不是程序里定义这个LOCAL符号(不知道如何在编译选项里定义符号的读者请参考附录),这样,提交之前不需要修改程序,进一步降低了出错的可能。
fopen方式
如果比赛要求用文件输入,但禁止用重定向的方式,可以如下操作:
程序2-9 数据统计(fopen版)
#include <stdio.h> #define INF 1000000000 int main() { FILE *fin, *fout; fin = fopen("data.in", "r"); fout = fopen("data.out", "w"); int x, n = 0, min = INF, max = -INF, s = 0; while (fscanf(fin, "%d", &x) != EOF) { s += x; if (x < min) min = x; if (x > max) max = x; n ++; } fprintf(fout, "%d %d %.3lf\n", min, max, (double)s/n); fclose(fin); fclose(fout); return 0; }
重定向和fopen两种方法各有优劣。重定向的方法写起来简单、自然,但是不能同时读写文件和标准输入输出;fopen的写法稍显繁琐,但是灵活性比较大(例如可以反复打开并读写文件)。顺便说一句,如果想把fopen版的程序改成标准输入输出,只需赋值
fin=stdin;fout=stdout;
即可,不要调用fopen和fclose。