好的,所以我有下面的代码,我只是从文件中提取各种东西并将它们输入到一个结构数组中,它看起来像#34;最初工作,但是当我在完成文件后打印它似乎已经用最后一个谷替换了所有的课程和名称,奇怪的是这不会发生整数(成绩),成绩确实得到了正常。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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);
}
我不确定我做错了什么:(这一切似乎都很简单,但不确定为什么它会用最新的一个替换所有内容。
答案 0 :(得分:3)
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;
}
答案 1 :(得分:1)
错误就在这里。
d[counter].name=name;
替换为:
d[counter].name = strdup(name); /*don't forget to free this memory.*/
课程的问题是一样的。
答案 2 :(得分:1)
这是对指针和char数组(字符串)的简单误解。这里有几页很好地解释了它们:
在您的情况下,您将结构指针值设置为等于从strtok返回的指针。很多这些字符串函数的工作原理是将结果放在某个内存地址并返回指向它的指针。返回的指针总是相同的,因此所有的struct值都将指向strtok调用的最后一个结果。
这就是你需要strdup(字符串重复)的原因。基本上,它接受给定地址的值,并将内容复制到内存中的新位置并返回值。