算法竞赛之【输入输出重定向】

当我们求解acm题目时,通常在设计好算法和程序后,要在调试环境(例如VC等)中运行程序,输入测试数据,当能得到正确运行结果后,才将程序提交到oj中。但由于调试往往不能一次成功,每次运行时,都要重新输入一遍测试数据,对于有大量输入数据的题目,输入数据需要花费大量时间。 

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

freopen("input.txt","r", stdin) ;

freopen("output.txt","w", stdout) ;

函数名:freopen
声明:FILE *freopen( const char *path, const char *mode, FILE *stream );
所在文件: stdio.h
参数说明:
path: 文件名,用于存储输入输出的自定义文件名。
mode: 文件打开的模式。和fopen中的模式(如r-只读, w-写)相同。
stream: 一个文件,通常使用标准流文件。
返回值:成功,则返回一个path所指定文件的指针;失败,返回NULL。(一般可以不使用它的返回值)
功能:实现重定向,把预定义的标准流文件定向到由path指定的文件中。标准流文件具体是指stdin、stdout和stderr。其中stdin是标准输入流,默认为键盘;stdout是标准输出流,默认为屏幕;stderr是标准错误流,一般把屏幕设为默认。

 

上述语句将使得scanf从文件input.txt 读入,printf 写入文件output.txt。事实上,不只是scanf和printf,所有读键盘输入、写屏幕输出的函数都将改用文件。尽管这样做很方便,并不是所有算法竞赛都允许用程序读写文件。甚至有的竞赛允许访问文件,但不允许用freopen这样的重定向方式读写文件。参赛之前请仔细阅读文件读写的相关规定。

 

下面以在VC下调试“计算a+b”的程序举例。
【C语法】

 1 #include <stdio.h> 
 2 int main() 
 3 { 
 4 int a,b; 
 5 freopen("debug\\in.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取 
 6 freopen("debug\\out.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中 
 7 while(scanf("%d %d",&a,&b)!=EOF) 
 8 printf("%d\n",a+b); 
 9 fclose(stdin);//关闭文件 
10 fclose(stdout);//关闭文件 
11 return 0; 
12 } 

【C++语法】

 1  2 #include <stdio.h> 
 2  3 #include <iostream.h> 
 3  4 int main() 
 4  5 { 
 5  6 int a,b; 
 6  7 freopen("debug\\in.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取 
 7  8 freopen("debug\\out.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中 
 8  9 while(cin>>a>>b) 
 9 10 cout<<a+b<<endl; // 注意使用endl 
10 11 fclose(stdin);//关闭文件 
11 12 fclose(stdout);//关闭文件 
12 13 return 0; 
13 14 } 

freopen("debug\\in.txt","r",stdin)的作用就是把标准输入流stdin重定向到debug\\in.txt文件中,这样在用scanf或是用cin输入时便不会从标准输入流读取数据,而是从in.txt文件中获取输入。只要把输入数据事先粘贴到in.txt,调试时就方便多了。 
类似的,freopen("debug\\out.txt","w",stdout)的作用就是把stdout重定向到debug\\out.txt文件中,这样输出结果需要打开out.txt文件查看。

 

提示

请在比赛之前了解文件读写的相关规定:是标准输入输出(也称标II/O,即直接读键盘、写屏幕), 还是文件输入输出?如果是文件输入输出,是否禁止用重定向方式的问文件?

需要说明的是:
1. 在freopen("debug\\in.txt","r",stdin)中,将输入文件in.txt放在文件夹debug中,文件夹debug是在VC中建立工程文件时自动生成的调试文件夹。如果改成freopen("in.txt","r",stdin),则in.txt文件将放在所建立的工程文件夹下。in.txt文件也可以放在其他的文件夹下,所在路径写正确即可。
2. 可以不使用输出重定向,仍然在控制台查看输出。
3. 程序调试成功后,提交到oj时不要忘记把与重定向有关的语句删除。

 

如果比赛中要求用文件输入输出,但禁止用重定向的方式,又当如何呢?

在算法竞赛中,如果不允许使用重定向方式读写数据,应使用fopen和fscant,fprintf进行输入输出。

我们还是以前面的例子为例:

【C语法】

 1 #include <stdio.h> 
 2 int main() 
 3 {
 4     int a,b;
 5     FILE *fin, *fout;
 6     fin = fopen("debug\\in.txt","rb");//debug\\in.txt 你的测试文件的实际路径
 7     fout = fopen("debug\\out.txt","wb");//
 8     while(fscanf(fin,"%d%d",&a,&b) == 2)
 9         fprintf(fout,"%d \n",a+b);
10     fclose(stdin);//关闭文件 
11     fclose(stdout);//关闭文件 
12     return 0; 
13 } 

【C++语法】

 1 #include <iostream>
 2 #include <fstream>
 3 using namespace std;
 4 int main() 
 5 {
 6     fstream fin,fout;//定义一个文件输入输出流对象
 7     int a,b;
 8     fin.open("debug\\in.txt",ios::in);//debug\\in.txt 你的测试文件的实际路径
 9     fout.open("debug\\out.txt",ios::out);
10     while(!fin.eof())
11     {
12         
13         fin>>a>>b;
14         if(fin.eof() == true)//如果文件到达末尾退出  eof()是文件流中的错误处理函数,它遇到文件结尾会返回true(一个非零值)。
15             break;
16         fout<<a+b<<endl;
17     }
18     
19     fin.close();//关闭文件 
20     fout.close();//关闭文件 
21     return 0; 
22 } 

 

重定向和fopen两种方法各有优劣。重定向的方法写起来简单、自然,但是不能同时读写文件和标准输入输出; fopen 的写法稍显繁琐,但是灵活性比较大(例如,可以反复打开开读写文件)。

【提示】

 如果想把fopen版的程序改成读写标准输入输出,只需赋值"fin = stdin; fout = stdout;" 即可,不要调用fopen和fclose。

 

posted @ 2018-06-10 10:18  底层码农  阅读(2796)  评论(4编辑  收藏  举报