首先,这是一个家庭作业,所以请不要为我编写任何代码,只需指出我的代码错误。
代码的基础是它是一本'地址/余额'书。我有一个带有变量的结构,但由于某种原因,我的双重链表正在搞乱,我无法弄清楚如何。有点花哨(不是真的)调试,我发现我认为fgets(字符串,200,文件); line会以某种方式覆盖我的head-> name指针,这似乎会抛弃其余的代码。相关代码片段在这里:
填充列表:
void populate_list(char* filename){
FILE *file = NULL;
char* name = NULL;
char* streetaddress = NULL;
char* city = NULL;
char* state = NULL;
char line[200];
int zip;
float balance;
file = fopen(filename,"r");
if(file==NULL){
printf("Invalid input file\n");
exit(1);
}
if(file == 0){
printf("Invalid file.\n");
exit(1);
}
while(!feof(file)){
fgets(line, 200, file);
name = strtok(line, ",");
streetaddress = strtok(NULL, ",");
city = strtok(NULL,",");
state = strtok(NULL,",");
zip = atoi(strtok(NULL,","));
balance = atof(strtok(NULL,","));
strip_spaces(name);
strip_spaces(streetaddress);
strip_spaces(city);
strip_spaces(state);
add_node(name, streetaddress, city, state, zip, balance);
}
fclose(file);
return;
}
然后是add_node代码:
void add_node(char* name, char* streetaddress, char* city, char* state, int zip, float, balance){
struct customer* addnode = NULL;
if(find_duplicate(name)){
print_filler(1);
printf("DUPLICATE RECORD: %s\n", name);
return;
} else {
addnode = (struct customer *) malloc(sizeof(struct customer));
addnode->name = name;
addnode->streetaddress = streetaddress;
addnode->city = city;
addnode->state = state;
addnode->zip = zip;
addnode->balance = balance;
if(head == NULL) {
head = addnode;
addnode->prev = NULL;
} else {
tail->next = addnode;
addnode->prev = tail;
}
tail = addnode;
addnode->next = NULL;
}
print_list();
return;
}
这个错误似乎是在第一次调用add_node之后发生的,并且在fgets()第二次关闭时发生。由于某种原因,它覆盖了整个fgets()行的head-> name。
还有其他随机的烦人的错误,我还没有确定,但我认为这可能是其他人的来源。
完整代码在这里,如果它有帮助:http://pastebin.com/k0pqyvT0
我的猜测是这与head->名称指针被fgets()覆盖有关,但我不能为我的生活弄清楚到底是做什么的,任何帮助/建议都会受到赞赏
编辑:解决方案是实现strdup()并在将字符串传递给add_node()时复制它们。谢谢你的所有答案。
答案 0 :(得分:2)
答案 1 :(得分:1)
我不知道它是否相关,但你的指针struct customer* addnode = NULL;
是一个本地的add_node(),它不会被保存(即每次函数退出时,它都会被破坏)。当使用指向char的指针时也要小心,它似乎直观地是一个字符串,但是有一个问题,
所以,如果你做的事情如下:
while(!feof(file)) {
name = strtoke(string, ",");
// etc
add_node(name, ... //etc);
}
因为您只复制引用即addnode->name = name
,所以下一行读取将替换用作前一条记录的相同指针的内容,因此您将拥有具有相同属性的列表。< / p>
答案 2 :(得分:1)
主要问题是您分配的节点成员指向line
缓冲区,每次调用fgets()
填充缓冲区时都会覆盖该缓冲区。所以每个节点中的指针总是指向同一个缓冲区(它存在于堆栈中)。
解决方案(如其他答案中所述)是使用strdup()
为每个节点成员分配的每个字符串的单独副本。所以这样的事情会起作用:
....
} else {
addnode = (struct customer *) malloc(sizeof(struct customer));
addnode->name = strdup(name);
addnode->streetaddress = strdup(streetaddress);
addnode->city = strdup(city);
addnode->state = strdup(state);
addnode->zip = strdup(zip);
addnode->balance = strdup(balance);
...
}
在分配节点之后立即清零节点的内容也是一个好主意,这样你就不会有垃圾:
addnode = (struct customer *) malloc(sizeof(struct customer));
memset(addnode, '\0', sizeof(struct customer));
答案 3 :(得分:0)
当 Dark Falcon 指出时,你* add_node *代码不正确。你需要做这样的事情:
void add_node(char* name, char* streetaddress, char* city, char* state, int zip, float balance){
struct customer* addnode = NULL;
strip_spaces(name);
strip_spaces(streetaddress);
strip_spaces(city);
strip_spaces(state);
if(find_duplicate(name)){
print_filler(1);
printf("DUPLICATE RECORD: %s\n", name);
return;
} else {
addnode = (struct customer *) malloc(sizeof(struct customer));
addnode->name = name;
addnode->streetaddress = streetaddress;
addnode->city = city;
addnode->state = state;
addnode->zip = zip;
addnode->balance = balance;
if(head == NULL) {
head = addnode;
addnode->prev = NULL;
} else {
tail->next = addnode;
addnode->prev = tail;
}
tail = addnode;
addnode->next = NULL;
}
print_list();
return;
}
然后像这样调用它:
add_node(strdup(name), strdup(streetaddress), strdup(city), strdup(state), zip, balance);