c-如何继续使用malloc



我有一个存储整数序列的文件。总整数的数量是未知的,所以如果我从文件中读取一个整数,我会继续使用malloc()来应用新的内存。我不知道我是否可以继续请求内存,并将它们添加到数组的末尾。Xcode不断警告我malloc()行中的EXC_BAD_EXCESS。如果我一直从文件中读取整数,我该怎么做?

int main()
{
    //1.read from file
    int *a = NULL;
    int size=0;
    //char ch;
    FILE *in;
    //open file
    if ( (in=fopen("/Users/NUO/Desktop/in.text","r")) == NULL){
        printf("cannot open input filen");
        exit(0);    //if file open fail, stop the program
    }
    while( ! feof(in) ){
        a = (int *)malloc(sizeof(int));
        fscanf(in,"%d", &a[size] );;
        printf("a[i]=%dn",a[size]);
        size++;
    }
fclose(in);
return 0;
}

像那样反复调用malloc()并不能达到你认为的效果。每次调用malloc(sizeof(int))时,它都会分配一个单独的、新的内存块,该内存块只够一个整数使用。写入a[size]的结果是,对于超过第一个值的每个值,都会写入该数组的末尾。

这里需要的是realloc()功能,例如

a = realloc(a, sizeof(int) * (size + 1));
if (a == NULL) { ... handle error ... }

重新编写代码,使size实际上是数组的大小,而不是它的最后一个索引,这将有助于简化此代码,但这既不存在也不存在。

  1. 不要使用malloc,而是使用realloc
  2. 不要在while循环中使用feof(in)。看看原因
int number;
while( fscanf(in, "%d", &number) == 1 ){
    a = realloc(a, sizeof(int)*(size+1));
    if ( a == NULL )
    {
       // Problem.
       exit(0);
    }
    a[size] = number;
    printf("a[i]=%dn", a[size]);
    size++;
}

您的malloc()正在用一个整数所需的空间覆盖您以前的存储!

a = (int *)malloc(sizeof(int));
 ^^^ assignment overwrites what you have stored!

相反,realloc()阵列:

a = realloc(a, sizeof(int)*(size+1));

您还没有分配整数数组,您在这里分配了一个整数。因此,您需要分配一个默认的数组大小,然后在即将过度运行时调整大小。这将在每次装满时将其大小调整为2。以这种方式调整它的大小可能不符合您的最佳利益,但您也可以为每个额外的字段重新分配每个字段。

size_t size = 0;
size_t current_size = 2;
a = (int *)malloc(sizeof(int) * current_size);
    if(!a)
        handle_error();

while( ! feof(in) ){
    if(size >= current_size) {
        current_size *= 2;
        a = (int *)realloc(a, sizeof(int) * current_size);
        if(!a)
            handle_error();
    }
    fscanf(in,"%d", &a[size] );;
    printf("a[i]=%dn",a[size]);
    size++;
}

通常的方法是首先分配一些空间(足够大,可以覆盖大多数情况),然后根据需要使用realloc函数将其加倍。

一个例子:

#define INITIAL_ALLOCATED 32 // or enough to cover most cases
...
size_t allocated = INITIAL_ALLOCATED;
size_t size = 0;
...
int *a = malloc( sizeof *a * allocated );
if ( !a )
  // panic
int val;
while ( fscanf( in, "%d", &val ) == 1 )
{
  if ( size == allocated )
  {
    int *tmp = realloc( a, sizeof *a * allocated * 2 ); // double the size of the buffer
    if ( tmp )
    {
      a = tmp;
      allocated *= 2;
    }
    else
    {
      // realloc failed - you can treat this as a fatal error, or you
      // can give the user a choice to continue with the data that's 
      // been read so far.  
    }
    a[size++] = val;
  }
}

我们首先将32个元素分配给a。然后我们从文件中读取一个值。如果我们不在数组的末尾(size不等于allocated),我们将该值添加到数组的末尾。如果我们在数组的末尾,则使用realloc将其大小加倍。如果realloc调用成功,我们将更新allocated变量以跟踪新的大小,并将值添加到数组中。我们一直走到输入文件的末尾。

每次达到限制时将数组大小增加一倍可以减少realloc调用的总数,如果您正在加载值,则可以节省性能。

注意,我将realloc的结果分配给了不同的变量tmp。如果realloc由于任何原因无法扩展数组,则它将返回NULL。如果我们将NULL值分配给a,我们将丢失对之前分配的内存的引用,从而导致内存泄漏。

还要注意,我们检查fscanf的结果,而不是调用feof,因为feof在我们已经尝试读取文件末尾之后才会返回true

相关内容

  • 没有找到相关文章

最新更新