这将是更接近我的版本的代码:
#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)) –