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