例題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;
}
提示
- 在Windows下,輸入完畢後先按Enter鍵,再按Ctrl+Z鍵,最後再按Enter 鍵,即可結束輸入。在Linux下,輸入完畢後按Ctrl+D鍵即可結束輸入。
- 把輸入數據保存在文件中,輸出數據也保存在文件中。這 樣,只要事先把輸入數據保存在文件中,就不必每次重新輸入了;數據輸出在文件中也避免 了“輸出太多,一卷屏前面的就看不見了”這樣的尷尬,運行結束後,慢慢瀏覽輸出文件即 可。如果有標準答案文件,還可以進行文件比較,而無須編程人員逐個檢查輸出是否正確。
- 使用文件最簡單的方法是使用輸入輸出重定向,只需在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;
}
這是一份典型的比賽代碼,包含了幾個特殊之處:
- 重定向的部分被寫在了#ifdef和#endif中。其含義是:只有定義了符號LOCAL,才編譯兩條freopen語句。 輸出中間結果的printf語句寫在了註釋中——它在最後版本的程序中不應該出現,但是又捨不得刪除它(萬一發現了新的bug,需要再次用它輸出中間信息)。將其註釋的好處 是:一旦需要時,把註釋符去掉即可。
- 上面的代碼在程序首部就定義了符號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;
}
提示
- 先聲明變量fin和fout(暫且不用考慮FILE*),把scanf改成fscanf,第一個參數爲fin;把printf改成fprintf,第一個參數爲fout,最後執行fclose,關閉兩 個文件。
- 在算法競賽中,如果不允許使用重定向方式讀寫數據,應使用fopen和 fscanf/fprintf進行輸入輸出。
- 如果想把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;
}
提示
- 在多數據的題目中,一個常見的錯誤是:在計算完一組數據後某些變量沒 有重置,影響到下組數據的求解。
- :當嵌套的兩個代碼塊中有同名變量時,內層的變量會屏蔽外層變量,有時 會引起十分隱蔽的錯誤。