在某些比赛中,会让选手从指定的文件中读入数据,然后把结果输出到指定文件中。C 语言提供了fopen函数,打开一个文件得到其文件指针,然后进行各种文件 I/O 的操作;C++ 中的文件流对象fstream也能进行文件 I/O 的操作。

上述这些方式在竞赛中都不常用,使用文件最简单的方式是输入输重定向 freopen 函数。

freopen的三个参数:

第一个参数表示需要重定向到的文件路径,如果和程序放在统一路径下,就只要给出文件名。 第二个参数表示访问方式,r表示读,w表示写。 第三个参数表示被重定向的文件流,stdin为标准输入,stdout为标准输出。

在 OI 比赛中,一般会规定输入输出的文件,你只需在开头加上两行freopen语句,后续的习题也会采用这种方式。

#include <cstdio>
using namespace std;
int main() {
 
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
 
return 0;
 
 
}

接下来,只需要正常使用 cin/cout 或 scanf/printf 就可以正常答题了。

freopen 可以打开本地的文件,例如 OI 比赛中会给大的测试用例,我们就可以使用 freopen 来进行数据读取。

在 CSP 比赛中,比赛会给选手提供大用例,我们可以通过 freopen 函数,来完成数据的测试。

有同学询问freopen 的使用方法,我在此对上课内容作总结回答。

OJ 做题是唯结果论的,主要分两步:

  • (1)猜测后台数据是什么;
  • (2)如何快速找到速度和时间在规定范围内的解题方法。

freopen 是将原本需要从键盘(stdin)导入或导出到屏幕(stdout)的文本,重定向到文件中,便于编辑和阅读。因此可以利用freopen 生成测试输入文件,利用freopen 将输入文件导入到程序中,利用freopen 将输出导出到文件中,便于阅读比较。

我们以“寻找第二大的数”题为例,题意大致为寻找给定四个数中第二大的数(即小于最大值的数中最大的数),如果四个数相同则输出该数。

初步测试为样例输入的测试。由于样例输入字符较多,测试又需要反复进行,人工输入耗时费力。可以将测试文件下载下来(“样例输入”标题后有下载图标),在程序中使用“freopen(“in.txt”,“r”,stdin);”将输入导向文本文件。以后每次运行时,由文本文件向程序供应输入。

类似地,当程序输出较多,而输出到屏幕输出难以阅读比较的时候,可以使用“freopen(“out.txt”,“w”,stdout);”将输出导向文本文件。便于反复打开使用。

以该题为例,我们应当测试0123、1023、1032、……等几种情况,但精确地划分测试类需要花费较多的思考时间,因此建议测试0000~3333 共4*4*4*4=256 种情形。做题人必须自制输入文件,同样利用freopen,书写“freopen(“in.txt”,“w”,stdout);”并运行程序。即:

#include <stdio.h>
int main()
{
 
freopen("in.txt", "w", stdout);
for (int i = 0; i < 4; i++)
    for (int i2 = 0; i2 < 4; i2++)
        for (int i3 = 0; i3 < 4; i3++)
            for (int i4 = 0; i4 < 4; i4++)
                printf("%d %d %d %d\n", i, i2, i3, i4);
 
 
}

则生成了输入文件,下次运行时,可以作为输入文件使用。

#include <stdio.h>
int main()
{
 
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
//(程序主体)
 
 
}

运行后,逐行检视,最终确定有问题的输入。再将 in.txt 清空,将有问题的输入写入。用断点调试(含:单步调试)调试程序,确定程序在哪里出问题。