访问结构中的char指针字段

时间:2012-08-02 08:28:16

标签: c pointers struct

我将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 Name1 ID1 marks1 Name2 ID2 marks2 Name3 ID3 marks3 2 Name4 ID4 marks4 Name5 ID5 marks5

这是代码。

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("");
            }

3 个答案:

答案 0 :(得分:1)

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

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

编辑:

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

答案 1 :(得分:1)

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

您有两种选择:

  • 将字段类型更改为字符数组。缺点是您必须指定最大长度并检查缓冲区溢出。
  • 使用动态内存。您可以使用strdupmalloc来使用动态内存。在这种情况下,您不得不在不再需要内存时释放(通过调用free),以避免内存泄漏。

答案 2 :(得分:1)

而不是

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

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

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

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