2.4 算法競賽中的輸入輸出框架

例題2-5 數據統計

輸入一些整數,求出它們的最小值、最大值和平均值(保留3位小數)。輸入保證這些 數都是不超過1000的整數。
樣例輸入:
2 8 3 5 1 7 3 6
樣例輸出:
1 8 4.375

程序2-9 數據統計(有bug)

#include<stdio.h> 
int main() 
{  
	int x, n = 0, min, max, s = 0;
	while(scanf("%d", &x) == 1)   
	{    
		s += x;    
		if(x < min) min = x;    
		if(x > max) max = x;    
		n++;  
	}
	printf("%d %d %.3f\n", min, max, (double)s/n);  
	return 0; 
}

提示

  1. 在Windows下,輸入完畢後先按Enter鍵,再按Ctrl+Z鍵,最後再按Enter 鍵,即可結束輸入。在Linux下,輸入完畢後按Ctrl+D鍵即可結束輸入。
  2. 把輸入數據保存在文件中,輸出數據也保存在文件中。這 樣,只要事先把輸入數據保存在文件中,就不必每次重新輸入了;數據輸出在文件中也避免 了“輸出太多,一卷屏前面的就看不見了”這樣的尷尬,運行結束後,慢慢瀏覽輸出文件即 可。如果有標準答案文件,還可以進行文件比較,而無須編程人員逐個檢查輸出是否正確。
  3. 使用文件最簡單的方法是使用輸入輸出重定向,只需在main函數的入口處加入以下兩條語句:加入以下兩條語句:
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);

上述語句將使得scanf從文件input.txt讀入,printf寫入文件output.txt。事實上,不只是scanf 和printf,所有讀鍵盤輸入、寫屏幕輸出的函數都將改用文件。儘管這樣做很方便,並不是所 有算法競賽都允許用程序讀寫文件。甚至有的競賽允許訪問文件,但不允許用freopen這樣的 重定向方式讀寫文件。參賽之前請仔細閱讀文件讀寫的相關規定。
4. 有一 種方法可以在本機測試時用文件重定向,但一旦提交到比賽,就自動“刪除”重定向 語句。代碼如下:

程序2-10 數據統計(重定向版)

#define LOCAL 
#include<stdio.h> 
#define INF 1000000000 
int main() 
{ 
	#ifdef LOCAL  
	freopen("data.in", "r", stdin);  
	freopen("data.out", "w", stdout); 
	#endif  
	int x, n = 0, min = INF, max = -INF, s = 0;  
	while(scanf("%d", &x) == 1)  
	{    
		s += x;    
		if(x < min) min = x;    
		if(x > max) max = x; 
		/*    printf("x = %d, min = %d, max = %d\n", x, min, max); */    
		n++;  
	}  
	printf("%d %d %.3f\n", min, max, (double)s/n);  
	return 0; 
}

這是一份典型的比賽代碼,包含了幾個特殊之處:

  1. 重定向的部分被寫在了#ifdef和#endif中。其含義是:只有定義了符號LOCAL,才編譯兩條freopen語句。 輸出中間結果的printf語句寫在了註釋中——它在最後版本的程序中不應該出現,但是又捨不得刪除它(萬一發現了新的bug,需要再次用它輸出中間信息)。將其註釋的好處 是:一旦需要時,把註釋符去掉即可。
  2. 上面的代碼在程序首部就定義了符號LOCAL,因此在本機測試時使用重定向方式讀寫文 件。如果比賽要求讀寫標準輸入輸出,只需在提交之前刪除#defineLOCAL即可。一個更好的方法是在編譯選項而不是程序裏定義這個LOCAL符號,這樣,提交之前不需要修改程序,進一步降低了出錯的可能。

程序2-11 數據統計(fopen版)

#include<stdio.h> 
#define INF 1000000000 
int main() 
{  
	FILE *fin, *fout;  
	fin = fopen("data.in", "rb");  
	fout = fopen("data.out", "wb");  
	int x, n = 0, min = INF, max = -INF, s = 0;  
	while(fscanf(fin, "%d", &x) == 1)  
	{    
		s += x;    
		if(x < min) min = x;    
		if(x > max) max = x;    n++;  
	}  
	fprintf(fout, "%d %d %.3f\n", min, max, (double)s/n);  
	fclose(fin);
  	fclose(fout);  
	return 0; 
}

提示

  1. 先聲明變量fin和fout(暫且不用考慮FILE*),把scanf改成fscanf,第一個參數爲fin;把printf改成fprintf,第一個參數爲fout,最後執行fclose,關閉兩 個文件。
  2. 在算法競賽中,如果不允許使用重定向方式讀寫數據,應使用fopen和 fscanf/fprintf進行輸入輸出。
  3. 如果想把fopen版的程序改成讀寫標準輸入輸出,只需賦值“fin =stdin;fout=stdout;”即可,不要調用fopen和fclose(10)。

例題2-6 數據統計II

輸入一些整數,求出它們的最小值、最大值和平均值(保留3位小數)。輸入保證這些 數都是不超過1000的整數。
輸入包含多組數據,每組數據第一行是整數個數n,第二行是n個整數。n=0爲輸入結束 標記,程序應當忽略這組數據。相鄰兩組數據之間應輸出一個空行。
樣例輸入:
8
2 8 3 5 1 7 3 6
4
-4 6 10 0
0
樣例輸出:
Case 1: 1 8 4.375
Case 2: -4 10 3.000

程序2-12 數據統計II(有bug)

#include<stdio.h> 
#define INF 1000000000 
int main() 
{  
	int x, n = 0, min = INF, max = -INF, s = 0, kase = 0;  
	while(scanf("%d", &n) == 1 && n)  
	{    
		int s = 0;    
		for(int i = 0; i < n; i++) 
		{      
			scanf("%d", &x);      
			s += x;      
			if(x < min) min = x;      
			if(x > max) max = x;    
		}    
		if(kase) printf("\n");    
		printf("Case %d: %d %d %.3f\n", ++kase, min, max, (double)s/n);  
	}  
	return 0; 
}

提示

  1. 在多數據的題目中,一個常見的錯誤是:在計算完一組數據後某些變量沒 有重置,影響到下組數據的求解。
  2. :當嵌套的兩個代碼塊中有同名變量時,內層的變量會屏蔽外層變量,有時 會引起十分隱蔽的錯誤。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章