繁体   English   中英

将文件中的数字读入数组

[英]Reading numbers from file into an array

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

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

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

通常,您需要将FILE *指针、 array 、指向index的指针和指向当前分配的内存max的指针传递给您的函数。 这样,你的函数可以从文件到数组读取数值,保持当前指数的计数来比较当前分配的大小,以便您可以realloc ,如果值的数量超过当前的分配。 最后,通过虚拟为您的indexmax分配使用指针,对任何一个的更改都可以立即返回到您的调用函数中(对于这些简短示例,通常是main()

将所有这些部分放在一起,您可以执行以下操作:

/* 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并根据需要分配/重新分配。但是,由于发生了对realloc的调用,数组a的值不能是静态声明的数组。此外,您必须分配在main()从函数返回到您的array 。如果'a'开始为NULL ,或者如果发生了realloc ,则返回一个新的指针地址。)

不需要在重新realloc后将新内存realloc ,但如果您稍后使用大于上次存储的值索引的索引迭代数组,它可以帮助防止无意中读取未初始化的值。

另请注意,当前的重新分配方案每次调用realloc时都会将内存量加倍。 您可以根据需要选择尽可能少地或尽可能多地添加。

有了这个,将它们放在一起的一个简短示例可能是:

#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 */
}

示例输入 100 Int

$ cat dat/100int.txt
27086
29317
32736
...
16892
8270
6444

示例使用/输出

$ ./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

内存错误检查

在您编写的任何动态分配内存的代码中,您对分配的任何内存块都有 2 个责任:(1) 始终保留一个指向内存块起始地址的指针,因此,(2) 当它不是时可以释放它不再需要。

您必须使用内存错误检查程序来确保您没有在分配的内存块之外/之外写入,尝试读取或基于未初始化的值进行跳转,并最终确认您已释放所有内存已分配。

对于 Linux valgrind是正常的选择。 有许多微妙的方法可以滥用新的内存块。 使用一个内存错误检查器允许您识别任何问题并确认正确使用的内存你分配,而不是找出问题通过一个存在segfault 每个平台都有类似的内存检查器。 它们都易于使用,只需通过它运行您的程序即可。

$ valgrind ./bin/fscanf_array_dyn dat/100int.txt
==7273== Memcheck, a memory error detector
==7273== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7273== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7273== Command: ./bin/fscanf_array_dyn dat/100int.txt
==7273==
 array[  0] : 27086
 array[  1] : 29317
 array[  2] : 32736
...
 array[ 97] : 16892
 array[ 98] : 8270
 array[ 99] : 6444
==7273==
==7273== HEAP SUMMARY:
==7273==     in use at exit: 0 bytes in 0 blocks
==7273==   total heap usage: 3 allocs, 3 frees, 1,336 bytes allocated
==7273==
==7273== All heap blocks were freed -- no leaks are possible
==7273==
==7273== For counts of detected and suppressed errors, rerun with: -v
==7273== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)

始终确认所有堆块都已释放——不可能发生泄漏,而且同样重要错误摘要:0 个上下文中的 0 个错误

仔细看一遍,如果您有任何其他问题,请告诉我。 基本的内存分配和释放是大部分 C 语言的基础。你最好现在花点时间完全理解代码,然后最终把你的头撞到你的桌子上......祝你编码好运。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM