结构数组替换自身的值
好的,所以我有下面的代码,我只是从文件中提取各种东西,并在结构数组中输入它们,它“看似”最初工作,但是当我完成文件后,我打印它似乎已经用最后一个谷替换了所有的课程和名称,奇怪的是这不会发生整数(成绩),成绩确实得到了正确的输入。
#include #include #include struct student { char *name; char *course; int grade; }; void courseSort(struct student d[20], int size); int main(void) { FILE* fp; char* filename = "grades.csv"; char buffer[100]; char* name, *class; char* del=","; int grade, i, counter=0; struct student d[20]; if((fp=fopen(filename, "r"))==NULL) { printf("unable to open %s\n", filename); exit(1); } while(fgets(buffer, sizeof(buffer), fp) !=NULL) { name = strtok(buffer,del); class=strtok(NULL,del); grade = atoi(strtok(NULL,del)); d[counter].name=name; d[counter].course=class; d[counter].grade=grade; printf("%s %s %d\n",d[counter].name,d[counter].course,d[counter].grade); counter++; } printf("\n\n\n"); for(i=0;i<counter;i++) printf("%s %s %d\n",d[i].name,d[i].course,d[i].grade); courseSort(d,counter); fclose(fp); }
我不确定我做错了什么:(这一切似乎都很简单,但不确定为什么它只是用最新的一个替换所有东西。
strtok
返回指向缓冲区的指针,不分配内存。 由于您不复制字符串,最终会有大量指向指向同一缓冲区的指针,这些指针在循环的每次迭代时都会被覆盖。
要解决此问题,您需要更改循环以使用strdup
复制字符串:
while(fgets(buffer, sizeof(buffer), fp) != NULL) { d[counter].name = strdup(strtok(buffer, del)); d[counter].course = strdup(strtok(NULL, del)); d[counter].grade = atoi(strtok(NULL, del)); counter++; }
一旦不再需要字符串,不要忘记free
返回已分配的内存:
for (i = 0; i < counter; i++) { free(d[i].name); free(d[i].course); d[i].name = NULL; d[i].course = NULL; }
请注意, strdup
是POSIX1.2001标准的一部分,不是C89的一部分。 如果它不可用,你必须自己重新实现它(非常简单):
char *my_strdup(const char *str) { char *copy; size_t len = strlen(str) + 1; if (len == 0) return NULL; copy = (char *)malloc(len); if (copy == NULL) return NULL; memcpy(copy, str, len); return copy; }
这是对指针和char数组(字符串)的简单误解。 这里有几页很好地解释了它们:
在您的情况下,您将结构指针值设置为等于从strtok返回的指针。 许多字符串函数通过将结果放在某个内存地址并返回指针来工作。 返回的指针总是相同的,因此所有的struct值都将指向strtok调用的最后一个结果。
这就是你需要strdup (String duplicate)的原因。 基本上它接受给定地址的值并将内容复制到内存中的新位置并返回值。
错误在这里。
d[counter].name=name;
用。。。来代替:
d[counter].name = strdup(name); /*don't forget to free this memory.*/
课程的问题是一样的。