2016-04-23 54 views
-1

我试图从文件中将数字读入数组。我尝试不同的方法,我用下面的代码上来:从文件中读取数字到数组中

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

看起来不错。它工作吗? –

+1

什么让你觉得你做错了什么?它似乎工作得很好。 – Dolda2000

+0

您可能想要获取stat文件中的整数数量。通过这种方式,您可以读取240多个整数的更多/ malloc空间。像'struct stat st; stat(文件名,&st); int numOfIntegers = st.st_size;' – Turtle

回答

1

通常,您需要将FILE *指针,array,指向index的指针和指向当前内存分配max的指针传递给您的函数。这样你的函数就可以从文件中读取数值到数组中,保持当前索引的数量与当前分配大小进行比较,所以如果值的数量超过当前分配,你可以使用realloc。最后,通过虚拟使用指针为您index和你max分配两者的变化要么是立即回到你的调用函数(通常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和分配/重新分配按需然而,该值与您的阵列a不能是静态声明数组因。致电realloc发生。此外,您必须将函数的返回分配给您的array,地址为main()。如果'a'NULL开始用,或者如果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诠释

$ 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个responsibilites:(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语言的基础。现在最好花时间去完全理解代码,然后最终在桌子上敲打你的头......用你的编码祝你好运。

+0

感谢你给出了这样详细的答案,我在这里学到了很多东西,其实这并不容易足以理解,但你解释得很好,我用你的代码,现在我是正确的值。 – user3057437

+0

很高兴我能帮上忙。C中有很多东西需要学习,并且很多细节都被掩盖了在几乎所有我读过的c参考文献中,你真正开始获得它的唯一方法就是编写足够的代码,在这些代码中绊入细微的点,大声呼救,最后灯泡亮起来。非常值得额外的努力,绊脚石和大声呼救。如果您对代码中的任何问题有任何疑问,请告诉我们,我很乐意进一步解释。 –