我正在尝试将文件中的数字输入数组。我尝试了不同的方法,我想出了以下代码:
int* readFileWithNumbers ()
{
FILE *file = fopen("number_list.txt", "r");
int*integers = malloc(sizeof(int) * 240);;
int i=0;
int num;
while(fscanf(file, "%d", &num) > 0) {
integers[i] = num;
i++;
}
fclose(file);
return integers;
}
我的输入文件格式为:
106
-18
248
-237
148
142
38
-189
59
-120
-219
-172
237
-257
-154
-267
-34
-292
239
-182
-243
-115
-26
-238
298
你能指导我,我在这里做错了吗?
答案 0 :(得分:1)
通常,您需要传递FILE *
指针,array
,指向index
的指针,以及指向当前内存分配max
的指针你的功能。这样,您的函数可以将文件中的值读入数组,保留当前索引的计数以与当前分配大小进行比较,因此如果值的数量超过当前分配,您可以realloc
。最后,通过为您的index
和max
分配虚拟使用指针,可以在您的调用函数中立即获得对这两者的更改(对于这些简短示例,通常为main()
。< / p>
将所有这些部分放在一起,你可以做类似的事情:
/* read array of unknown size int 'a' from 'fp' */
int *readarr (FILE *fp, int *a, size_t *idx, size_t *max)
{
int tmp;
if (!a) /* if a not allocated -- allocate/validate */
if (!(a = calloc (1, *max * sizeof *a))) {
fprintf (stderr, "readarr() virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
while (fscanf (fp, " %d", &tmp) == 1) { /* for each int in file */
if (*idx == *max) { /* check idx and max */
void *ap = realloc (a, 2 * *max * sizeof *a); /* realloc */
if (!ap) { /* validate realloc success */
fprintf (stderr, "realloc() error: memory exhausted.\n");
break; /* if failure, return with exising data */
}
a = ap; /* assign new mem block, zero new mem */
memset (ap + *max * sizeof *a, 0, *max * sizeof *a);
*max *= 2; /* update allocation size */
}
a[(*idx)++] = tmp; /* add int to array, update index */
}
return a; /* return array */
}
(注意:该函数将接受已分配的数组,或NULL
并根据需要分配/重新分配。但是,数组a
的值不能是静态的由于调用了realloc
而声明了数组。此外,您必须将函数的返回值分配给array
中的main()
。如果'a'
为{{1}开始时,或者如果发生NULL
,则返回一个新的指针地址。)
在不需要realloc
之后将新内存归零,但如果稍后使用大于上一个存储值索引的索引迭代数组,它可以帮助防止无意识读取未初始化的值。
另请注意,当前重新分配方案每次调用realloc
时内存量都会增加一倍。您可以根据需要选择添加尽可能少的内容。
有了它,一个简短的例子就是:
realloc
示例输入100 Int
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXI 64
int *readarr ( FILE *fp, int *a, size_t *idx, size_t *max);
int main (int argc, char **argv) {
int *array = NULL; /* pointer to array */
size_t i = 0, n = 0, maxi = MAXI; /* index, initial elements */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* valildate file pointer */
fprintf (stderr, "error: file open failed. '%s'\n",
argc > 1 ? argv[1] : "stdin");
return 1;
}
array = readarr (fp, array, &n, &maxi); /* read values from file */
if (fp != stdin) fclose (fp); /* close file */
for (i = 0; i < n; i++) /* print array */
printf (" array[%3zu] : %d\n", i, array[i]);
free (array); /* free memory */
return 0;
}
/* read array of unknown size int 'a' from 'fp' */
int *readarr (FILE *fp, int *a, size_t *idx, size_t *max)
{
int tmp;
if (!a) /* if a not allocated -- allocate/validate */
if (!(a = calloc (1, *max * sizeof *a))) {
fprintf (stderr, "readarr() virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
while (fscanf (fp, " %d", &tmp) == 1) { /* for each int in file */
if (*idx == *max) { /* check idx and max */
void *ap = realloc (a, 2 * *max * sizeof *a); /* realloc */
if (!ap) { /* validate realloc success */
fprintf (stderr, "realloc() error: memory exhausted.\n");
break; /* if failure, return with exising data */
}
a = ap; /* assign new mem block, zero new mem */
memset (ap + *max * sizeof *a, 0, *max * sizeof *a);
*max *= 2; /* update allocation size */
}
a[(*idx)++] = tmp; /* add int to array, update index */
}
return a; /* return array */
}
示例使用/输出
$ cat dat/100int.txt
27086
29317
32736
...
16892
8270
6444
内存错误检查
在你的动态分配内存的任何代码中,你有2个责任关于任何分配的内存块:(1)总是保留一个指向内存块起始地址的指针,所以,(2)它可以在释放时释放它不再需要了。
必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,最后确认您已拥有释放了你分配的所有内存。
对于Linux $ ./bin/fscanf_array_dyn dat/100int.txt
array[ 0] : 27086
array[ 1] : 29317
array[ 2] : 32736
array[ 3] : 3356
...
array[ 97] : 16892
array[ 98] : 8270
array[ 99] : 6444
是正常的选择。有许多微妙的方法可以滥用新的内存块。使用内存错误检查器可以识别任何问题并验证您分配的内存的正确使用情况,而不是通过valgrind
找出问题。每个平台都有类似的记忆检查器。它们都很简单易用,只需通过它运行程序即可。
segfault
始终确认释放所有堆块 - 不可能泄漏并且同样重要错误摘要:0个上下文中的0个错误。
仔细看看,如果您有任何其他问题,请告诉我。基本分配和释放内存是C大部分时间的基础。现在花些时间来完全理解代码,然后最后在你的桌面上敲打你的头,你的头更好......祝你的编码好运。