1

我有一个struct定义为

typedef struct
{
    char* name;
    char* ID;
    int marks;

    char* details;

} Student;

另一个作为

typedef struct
{
    int n;
    Student* stud_array;
} Batch;

一个文件具有特定格式的不同批次学生的条目,我正在从该文件中读取以填充BatchArray类型Batch*

填充每个字段后,我正在使用

puts(BatchArray[no_of_batches-1].stud_array[i].name);
puts(BatchArray[no_of_batches-1].stud_array[i].ID);
printf("%d\n",BatchArray[no_of_batches-1].stud_array[i].marks);

看看结果。它给了我正确的输出。

但是,一切都完成后,当我想遍历 时BatchArray,只有marks每个结构中的字段保留该值。和显示nameID一些随机垃圾值。

迭代代码是标准的。尽管如此,它就在这里。

   for(i = 0; i < no_of_batches; i++)   {
        currBSize = BatchArray[i].n;
        printf("Batch %d\n", (i+1));
        printf("Batch size %d\n", currBSize);
        for(j = 0; j < currBSize; j++)  {
            puts(BatchArray[i].stud_array[j].name);
        }
    }

我正在处理的问题需要找到每批的平均分数,所以这不是问题。但我想知道为什么其他字段被重置为垃圾值。

有人可以帮忙吗?

编辑:这是我填充字段的方式。

该文件由这样的条目组成

3 名称1 ID1 标记1 名称2 ID2 标记2 名称3 ID3 标记3 2 名称4 ID4 标记4 名称5 ID5 标记5

这就是代码。

no_of_batches = 0;
            infileptr = fopen (infilename, "r");

            BatchArray = (Batch *) malloc(sizeof(no_of_batches));

            int MAX_BUFF = 100;
            char currLine[MAX_BUFF];    

            while (fgets(currLine, MAX_BUFF, infileptr) != NULL)    {

                no_of_batches++;
                BatchArray = (Batch *) realloc(BatchArray, no_of_batches*sizeof(Batch));
                currBatchSize = atoi(currLine);
                BatchArray[no_of_batches-1].n = currBatchSize;
                printf("currBatchSize : %d\n",BatchArray[no_of_batches-1].n);
                BatchArray[no_of_batches-1].stud_array = (Student *) malloc(currBatchSize*sizeof(Student));
                for(i = 0; i < currBatchSize; i++)  {
                    fgets(currLine, MAX_BUFF, infileptr);
                    currLine[strlen(currLine)-1] = '\0';

                    BatchArray[no_of_batches-1].stud_array[i].details = currLine;

                    //getting the Name from currLine
                    j = 0;
                    len = strlen(currLine);
                    char buildName[len];
                    while(currLine[j] != ' ')   {
                        buildName[j] = currLine[j];
                        j++;
                    }

                    buildName[j] = '\0';
                    BatchArray[no_of_batches-1].stud_array[i].name = buildName;

                    j++;
                    //getting the ID from currLine
                    k = 0;
                    char buildID[len];
                    while(currLine[j] != ' ')   {
                        buildID[k] = currLine[j];
                        j++;
                        k++;
                    }

                    buildID[k] = '\0';
                    BatchArray[no_of_batches-1].stud_array[i].ID = buildID;

                    puts(BatchArray[no_of_batches-1].stud_array[i].name);
                    puts(BatchArray[no_of_batches-1].stud_array[i].ID);

                    //getting the marks from currLine
                    k = 0;
                    j++;
                    char buildMarks[len];
                    while(currLine[j] != '\0')  {
                        buildMarks[k] = currLine[j];
                        j++;
                        k++;
                    }

                    buildMarks[k] = '\0';
                    BatchArray[no_of_batches-1].stud_array[i].marks = atoi(buildMarks);
                    printf("%d\n",BatchArray[no_of_batches-1].stud_array[i].marks);
                }
                puts("");
            }
4

3 回答 3

1

我的猜测是你没有为nameID字段分配内存。由于 name 和 ID 字段都是 char 指针,因此您需要在填充它们之前分别为它们中的每一个分配内存。

如果您在填充字段的位置发布代码,那么人们将能够为您提供更准确的理由。

编辑:

您正在使用相同的局部变量 buildName 和 buildID 来填充不同学生的值。当您将局部变量分配给结构字段时,其中存储的是这些变量的地址,这些地址中的值会随着循环的迭代而不断变化。另一个问题是,一旦您从函数返回,局部变量就会超出范围。因此,建议使用 malloc 为名称和 ID 字段分配内存或使用 strdup(您可以参考下面关于使用 strdup 的 ectamur 的回答)。

于 2012-08-02T08:31:39.647 回答
1

字段nameID的类型为char*,即它们是指针。如果在加载和迭代之间,它们指向的内存被覆盖,那么它们指向垃圾。在这种情况下,您似乎将字段分配给数组name的起始地址,该 buildName数组作为局部变量被分配到堆栈上。

您有两种选择:

  • 将字段类型更改为字符数组。缺点是您必须指定最大长度并检查缓冲区溢出。
  • 使用动态内存。您可以使用strdup或来使用动态内存mallocfree在这种情况下,您必须在不再需要内存时释放(通过调用),以避免内存泄漏。
于 2012-08-02T08:39:21.063 回答
1

代替

    BatchArray[no_of_batches-1].stud_array[i].name = buildName;

    BatchArray[no_of_batches-1].stud_array[i].name = strdup(buildName);

第一种情况的问题是name指向buildName,它是堆栈上的一个数组,只要堆栈的内容发生变化,就会被覆盖。

在第二种情况下,您已将数组复制到新分配的堆内存(与mallocor一样realloc),在您之前将保持不变free

于 2012-08-02T08:53:04.413 回答