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


當我們求解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。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM