算法競賽之【輸入輸出重定向】

當咱們求解acm題目時,一般在設計好算法和程序後,要在調試環境(例如VC等)中運行程序,輸入測試數據,當能獲得正確運行結果後,纔將程序提交到oj中。但因爲調試每每不能一次成功,每次運行時,都要從新輸入一遍測試數據,對於有大量輸入數據的題目,輸入數據須要花費大量時間。 ios

一個好的方法是用文件一一把輸入數據保存在 文件中,輸出數據也保存在文件中。這樣,只要事先把輸入數據保存在文件中,就沒必要每次從新輸入了;數據輸出在文件中也避免了「輸出太多,一卷屏前面的就看不見了」這樣的尷尬,運行結束後,慢慢瀏覽輸出文件便可。若是有標準答案文件,還能夠進行文件比較」,而無須編程人員逐個檢查輸出是否正確。事實上,幾乎全部算法競賽的輸入數據和標準答案都是保存在文件中的。使用文件最簡單的方法是使用輸入輸出重定向,只需在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這樣的重定向方式讀寫文件。參賽以前請仔細閱讀文件讀寫的相關規定。spa

 

下面以在VC下調試「計算a+b」的程序舉例。
【C語法】debug

 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。

相關文章
相關標籤/搜索