我将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
字段保留该值。 name
和ID
显示为一些随机垃圾值。
迭代代码是标准的。不过,这就是。
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("");
}
答案 0 :(得分:1)
我的猜测是你没有为name
和ID
字段分配内存。由于name和ID字段都是char指针,因此在填充之前需要分别为每个字段分配内存。
如果您在填写字段的位置发布代码,那么SO人员将能够为您提供更准确的理由。
编辑:
您正在使用相同的局部变量buildName和buildID来填充不同学生的值。将局部变量分配给结构字段时,存储在其中的是这些变量的地址,这些变量中的值会随着循环遍历而不断变化。另一个问题是,一旦从函数返回,局部变量就会超出范围。因此,建议使用malloc为名称和ID字段分配内存或使用strdup(您可以参考以下关于使用strdup的ectamur的答案)。
答案 1 :(得分:1)
字段name
和ID
属于char*
类型,即它们是指针。如果在加载和迭代之间它们指向的内存被覆盖,那么它们指向垃圾。在这种情况下,您似乎将字段name
分配给作为局部变量的buildName
数组的起始地址,并将其分配到堆栈中。
您有两种选择:
strdup
或malloc
来使用动态内存。在这种情况下,您不得不在不再需要内存时释放(通过调用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
,这是堆栈中的一个数组,只要堆栈内容发生变化,它就会被覆盖。
在第二种情况下,您已将数组复制到新分配的堆内存(与malloc
或realloc
一样),在您free
之前,它将保持不变。