退出循环后,为什么数组中的值会发生变化?

时间:2015-01-27 02:19:59

标签: c arrays loops realloc

由于某种原因退出while循环后,数组中的值发生了变化,但我不是原因。在循环内部,值是正确的,它们通常存储在数组(a)内。这是在c!

int * readFile()
{
    char file_name[50];
    printf("Enter the name of the file to open:\n");
    scanf("%s",file_name);
    FILE *fp;
    fp = fopen(file_name,"r");

    if(fp == NULL )
    {
            printf("Sorry but the File you entered cannot be opened\n");
            int *b;
            b[0] = -1;
            return b;
    }

            int *a;
            int j=0;
            long int value=0;
            while (fscanf(fp,"%d",&value)!=EOF) {
                    if((a =malloc(sizeof(long int))) == NULL)
                            printf("not enough memory\n");
                    a[j]=value;
                    j++;
            }
            printf("%d %d %d\n",a[0],a[1],a[2]);
            int i=0;
            for(i=0; i<j;i++)
            {
                    printf("array[%d] = %d\n",i,a[i]);
            }
            fclose(fp);
            return a;
}

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:0)

执行if((a =malloc(sizeof(long int))) == NULL)时,您只为单个long int(大小为32位)分配足够的内存,但是您需要为计划存储的每个int分配内存。因为malloc分配了一块内存,所以您需要知道您计划存储多少个int。如果您不介意开销,可以通过正在读取的文件进行初步运行并计算您将读取的整数(基本上是您的j变量),然后就可以了

a =malloc( intCounter * sizeof(long int))) == NULL,其中intCounter将是文件(j)中的整数总数。

另一种选择是使用链接列表(它接近你想要做的事情),你可以动态地为每个int分配内存,但是你需要将指针信息存储到下一个节点中。阵列。

while循环中的malloc调用将覆盖存储在Int的单个分配中的数据。例如,如果您从文本文件中读取1 2 3,它将在a,malloc不同的内存地址中存储1,存储2,malloc,另一个内存地址和存储3.导致打印0,0,3。

答案 1 :(得分:0)

您在代码中使用了intlong int混合。你需要建立一致的类型;对于我的回答我和int一起走了。 (您可以轻松浏览并将所有int更改为long,只要您还将fscanf格式字符串更改为%ld)。

目前,您每次在循环中分配一个long int的新块。除了从先前的循环迭代中泄漏内存之外,您还可以访问此界限。此外,当malloc失败时,您打印一条消息并继续前进!

相反,您需要分配一个包含多个整数的块。一种方法是使用realloc函数使现有分配更大。

此外,在检查fscanf的返回值时,您应该在此处检查== 1。如果他们输入了一些字母但没有触发EOF条件,它将返回0,因此您的程序将永远继续。

以下是该循环的样子:

int *a = NULL;
size_t j = 0;

while ( fscanf(fp,"%d",&value) == 1 )
{
    int *ptr = realloc( a, (j+1) * sizeof *a );
    if ( !ptr )
    {
        printf("not enough memory\n");
        break;
    }

    a = ptr;
    a[j]=value;
    j++;
}

通过为新分配使用单独的变量ptr,我们可以从内存不足的情况中恢复(程序可以继续使用到目前为止输入的整数的数量)。

如果您打算通过立即退出程序来处理内存不足(例如通过调用exit(EXIT_FAILURE);而不是break;,那么您可以使用a = realloc( a,等缩短代码而不是ptr


早期的代码int *b; b[0] = -1;有一个问题:b并不指向任何地方,但您通过它进行了书写。

此功能存在设计问题,因为呼叫者无法知道j是什么。对此的一个解决方案是始终将-1放在输入的末尾(这个想法被称为&#34; sentinel值&#34; - 并且记得为它分配空间);另一种选择是拥有一个&#34; out&#34;函数的参数。