如何在C编程中使用多个动态分配?

时间:2022-09-23 08:00:28

I'm making a program that reads two sets of data (float) from two different .txt files, and then it transfers these data to two different arrays, which will be used in further calculations. However, when I try to use dynamic allocation more than once, something goes wrong and the data seem not to be stored in the array.

我正在制作一个程序,从两个不同的.txt文件中读取两组数据(浮点数),然后将这些数据传输到两个不同的数组,这些数组将用于进一步的计算。但是,当我尝试多次使用动态分配时,出现问题并且数据似乎不会存储在数组中。

The following simplified program seems to be working fine:

以下简化程序似乎工作正常:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    float *VarA;
    int n = 0;
    int *counter;
    int i;
    FILE *input1;

    input1 = fopen("C:\\Users\\...test.txt","r");

    VarA = (float*)calloc(20001, sizeof(float));

    for(i = 0; i < 20001; i++)
    {
        fscanf(input1,"%f",&VarA[i]);
        printf("%f\n",VarA[i]);
    }

    free(VarA);

    fclose(input1);

    return 0;
}

it successfully shows the data stored in the array VarA. However, if I introduce a new array to count the number of lines in the file (which is necessary for my further calculations), I just get the value 0.000000 from every array element:

它成功显示存储在数组VarA中的数据。但是,如果我引入一个新数组来计算文件中的行数(这是我进一步计算所必需的),我只是从每个数组元素得到0.000000的值:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    float *VarA;
    int n = 0;
    int *counter;
    int i;
    FILE *input1;

    input1 = fopen("C:\\Users\\...test.txt","r");

    counter = (int*)calloc(100000, sizeof(int));

    while(fscanf(input1,"%f",&counter[n]) != EOF)
    {
        n++;
    }

    free(counter);

    printf("n = %i\n", n);

    VarA = (float*)calloc(n, sizeof(float));

    for(i = 0; i < n; i++)
    {
        fscanf(input1,"%f",&VarA[i]);
        printf("%f\n",VarA[i]);
    }

    free(VarA);

    fclose(input1);

    return 0;
}

I know that I can avoid using another array to count the number of lines. The point is that every time I use another array, for any purpose, I get the same result. For instance, if I don't use an array to count the number of lines, but I make another one to store my other set of data, one of these arrays just won't present the data after the reading. I tried to modify my program several times in order to find the source of such behavior, but without success.

我知道我可以避免使用另一个数组来计算行数。关键是每次我使用另一个数组时,出于任何目的,我得到相同的结果。例如,如果我不使用数组来计算行数,但是我使用另一个数组来存储我的另一组数据,则其中一个数组在读取后不会显示数据。我试图多次修改我的程序,以找到这种行为的来源,但没有成功。

2 个解决方案

#1


4  

(At least) two major problems: first,

(至少)两个主要问题:第一,

counter = (int*)calloc(100000, sizeof(int));
while(fscanf(input1,"%f",&counter[n]) != EOF) {
    n++;
}
free(counter);

is basically saying "Grab me a chunk of memory, fill it with data as I read the file, then throw it away without ever using it." Probably not what you intended. Then,

基本上是说“抓住我一大块内存,在读取文件时填充数据,然后扔掉它而不使用它。”可能不是你想要的。然后,

VarA = (float*)calloc(n, sizeof(float));
for (i = 0; i < n; i++) {
    fscanf(input1,"%f",&VarA[n]);
    printf("%f\n",VarA[n]);
}
free(VarA);

which says, "Grab a big chunk of memory, then read data from after the end of the file I just read everything from, put it there, then throw it away."

它说:“抓住一大块内存,然后在文件结束后读取数据,我只需读取所有内容,将其放在那里,然后扔掉。”

If you want to read the data from the same file again, you'll have to close it an reopen it (or "seek" to the start). And if you want to do anything with it, you'll have to do it before free()ing the memory you loaded it into.

如果您想再次读取同一文件中的数据,则必须将其关闭并重新打开(或“搜索”到开头)。如果你想对它做任何事情,你必须在免费()加载它的内存之前做。

#2


3  

counter = (int*)calloc(100000, sizeof(int));
         // ^--- `int*`                ^--- `int`
                          // v--- `int` pointer
while(fscanf(input1,"%f",&counter[n]) != EOF)
                   // ^--- `float` designator

Do you see any discrepancies here? Your code allocates ints, then passes a pointer to those ints to fscanf telling it they're floats (using the %f designator). According to the C standard draft n1570, section 7.21.6.2p10 this constitutes undefined behaviour:

你觉得这里有什么差异吗?您的代码分配整数,然后将指针传递给fscanf,告诉它们它们是浮点数(使用%f指示符)。根据C标准草案n1570,第7.21.6.2p10节,这构成了未定义的行为:

If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.

如果此对象没有适当的类型,或者无法在对象中表示转换结果,则行为未定义。

My suggestion would be to use the * assignment suppression modifier here, for example:

我的建议是在这里使用*赋值抑制修饰符,例如:

while (fscanf(input1, "%*f") != EOF) n++;

or, alternatively

或者,或者

while (fscanf(input1, "%f", &(float){0}) != 1) n++;

Note also how I've changed the check from EOF to 1. You can find more information about the return values of fscanf here (which you really should read before using any scanf-related function... and stop guessing, because guessing in C can be harmful).

另请注意我是如何将检查从EOF更改为1.您可以在此处找到有关fscanf返回值的更多信息(在使用任何与scanf相关的函数之前您应该阅读它...并停止猜测,因为在C中猜测可能是有害的)。

Additionally, you need to rewind your file once it reaches EOF, otherwise every call to fscanf following this loop will return EOF:

此外,您需要在文件到达EOF时回放文件,否则在此循环后每次调用fscanf将返回EOF:

rewind(input1);

P.S. Don't cast malloc in C. This goes for calloc and realloc, too. There's a lot of this quoted stuff that has opengroup manuals of its own; I'll leave it as an exercise to you to find (and read) the opengroup manuals.

附:不要在C中强制使用malloc。这也适用于calloc和realloc。有很多引用的东西都有自己的opengroup手册;我将把它作为练习留给你找到(并阅读)opengroup手册。

#1


4  

(At least) two major problems: first,

(至少)两个主要问题:第一,

counter = (int*)calloc(100000, sizeof(int));
while(fscanf(input1,"%f",&counter[n]) != EOF) {
    n++;
}
free(counter);

is basically saying "Grab me a chunk of memory, fill it with data as I read the file, then throw it away without ever using it." Probably not what you intended. Then,

基本上是说“抓住我一大块内存,在读取文件时填充数据,然后扔掉它而不使用它。”可能不是你想要的。然后,

VarA = (float*)calloc(n, sizeof(float));
for (i = 0; i < n; i++) {
    fscanf(input1,"%f",&VarA[n]);
    printf("%f\n",VarA[n]);
}
free(VarA);

which says, "Grab a big chunk of memory, then read data from after the end of the file I just read everything from, put it there, then throw it away."

它说:“抓住一大块内存,然后在文件结束后读取数据,我只需读取所有内容,将其放在那里,然后扔掉。”

If you want to read the data from the same file again, you'll have to close it an reopen it (or "seek" to the start). And if you want to do anything with it, you'll have to do it before free()ing the memory you loaded it into.

如果您想再次读取同一文件中的数据,则必须将其关闭并重新打开(或“搜索”到开头)。如果你想对它做任何事情,你必须在免费()加载它的内存之前做。

#2


3  

counter = (int*)calloc(100000, sizeof(int));
         // ^--- `int*`                ^--- `int`
                          // v--- `int` pointer
while(fscanf(input1,"%f",&counter[n]) != EOF)
                   // ^--- `float` designator

Do you see any discrepancies here? Your code allocates ints, then passes a pointer to those ints to fscanf telling it they're floats (using the %f designator). According to the C standard draft n1570, section 7.21.6.2p10 this constitutes undefined behaviour:

你觉得这里有什么差异吗?您的代码分配整数,然后将指针传递给fscanf,告诉它们它们是浮点数(使用%f指示符)。根据C标准草案n1570,第7.21.6.2p10节,这构成了未定义的行为:

If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.

如果此对象没有适当的类型,或者无法在对象中表示转换结果,则行为未定义。

My suggestion would be to use the * assignment suppression modifier here, for example:

我的建议是在这里使用*赋值抑制修饰符,例如:

while (fscanf(input1, "%*f") != EOF) n++;

or, alternatively

或者,或者

while (fscanf(input1, "%f", &(float){0}) != 1) n++;

Note also how I've changed the check from EOF to 1. You can find more information about the return values of fscanf here (which you really should read before using any scanf-related function... and stop guessing, because guessing in C can be harmful).

另请注意我是如何将检查从EOF更改为1.您可以在此处找到有关fscanf返回值的更多信息(在使用任何与scanf相关的函数之前您应该阅读它...并停止猜测,因为在C中猜测可能是有害的)。

Additionally, you need to rewind your file once it reaches EOF, otherwise every call to fscanf following this loop will return EOF:

此外,您需要在文件到达EOF时回放文件,否则在此循环后每次调用fscanf将返回EOF:

rewind(input1);

P.S. Don't cast malloc in C. This goes for calloc and realloc, too. There's a lot of this quoted stuff that has opengroup manuals of its own; I'll leave it as an exercise to you to find (and read) the opengroup manuals.

附:不要在C中强制使用malloc。这也适用于calloc和realloc。有很多引用的东西都有自己的opengroup手册;我将把它作为练习留给你找到(并阅读)opengroup手册。