将数字从文件读入数组

时间:2016-04-23 01:43:37

标签: c unix io

我正在尝试将文件中的数字输入数组。我尝试了不同的方法,我想出了以下代码:

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

你能指导我,我在这里做错了吗?

1 个答案:

答案 0 :(得分:1)

通常,您需要传递FILE *指针,array,指向index的指针,以及指向当前内存分配max的指针你的功能。这样,您的函数可以将文件中的值读入数组,保留当前索引的计数以与当前分配大小进行比较,因此如果值的数量超过当前分配,您可以realloc。最后,通过为您的indexmax分配虚拟使用指针,可以在您的调用函数中立即获得对这两者的更改(对于这些简短示例,通常为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大部分时间的基础。现在花些时间来完全理解代码,然后最后在你的桌面上敲打你的头,你的头更好......祝你的编码好运。