這將是更接近我的版本的代碼:
#include <stdio.h>
#include <stdlib.h>
static int input(int size, int arr[])
{
const char file[] = "data.txt";
FILE *f = fopen(file, "r");
if (f == NULL)
{
fprintf(stderr, "Failed to open file '%s' for reading\n", file);
exit(EXIT_FAILURE);
}
int i;
for (i = 0; i < size && fscanf(f, "%d", &arr[i]) == 1; i++)
;
fclose(f);
return i;
}
int main(void)
{
int arr[50];
int num = input(50, arr);
for (int i = 0; i < num; i++)
printf("%d: %d\n", i, arr[i]);
return 0;
}
函數之前使用的static
要平息-Wmissing-prototypes
。函數main()
告訴input()
函數有多少元素在數組中,所以函數可以避免溢出緩衝區(不會出現堆棧溢出)。函數input()
告訴main()
函數讀取了多少個值,因此main()
函數不會訪問未初始化的數據。關鍵的函數調用是錯誤檢查 - fopen()
和fscanf()
。
的代碼完全編譯使用GCC 6.3.0運行MACOS塞拉利昂10.12.4以下(源文件是rf19.c
)命令行一個Mac和上:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -Wold-style-definition rf19.c -o rf19
$
我所生成的數據文件23的隨機整數在10到99之間,輸出爲:
$ ./rf19
0: 48
1: 33
2: 77
3: 42
4: 78
5: 51
6: 85
7: 56
8: 55
9: 56
10: 16
11: 38
12: 39
13: 52
14: 34
15: 63
16: 20
17: 23
18: 23
19: 19
20: 39
21: 44
22: 71
$
這不是可怕的信息,但總比沒有好。
該代碼仍有缺陷,我不打算修復 - 有些比其他更嚴重。例如,文件名是固定的 - 這是一個禁忌。 input()
函數中的代碼出錯時退出;這不一定好。它在標準錯誤上產生一個錯誤消息 - 這比標準輸出更好,但在GUI應用程序中不是一個好主意。產量浪費了很多水平空間;顯示的數據,你可以得到每個輸出行10個值(每行約70個字符),但打印更復雜,所以我沒有顯示它。代碼將EOF和數據中的單詞或標點符號對待;這可能會或可能不重要,這取決於您的應用程序。輸入僅在第50次輸入後停止;也許你需要知道是否有更多的條目可供閱讀。我可能會將命令行參數作爲文件名進行處理,或者在沒有指定文件的情況下處理標準輸入 - Unix'filter command'習語。我可能會做一些比打印前五十個值更令人興奮的東西。我可能會將文件讀取代碼放在與文件打開/關閉代碼不同的函數中。
'arr [i]'永遠不會等於'EOF',所以你永遠循環並最終發生段錯誤。你也將第一個元素的地址傳遞給'input()',所以你試圖寫入你從一開始就不擁有的內存。 –
'input(&arr [50])'應該是'input(arr)' – Barmar
在使用文件指針前,您不檢查是否成功打開了輸入文件。這很容易導致崩潰(並且很容易修復 - 總是檢查來自'fopen()'或任何其他類似開放函數的返回值)。你不檢查'fscanf()'的返回值;那也是一個錯誤。 (請參閱[我們如何檢查'scanf()'的返回值?](http://stackoverflow.com/questions/10084224)) –