我使用以下代码将节点添加到双链表并按照word
按字母顺序排列它们。节点由char * word
,struct NODES * prev
和struct NODES * next
组成。我在阅读file testing a
后,列表看起来像NULL <- a <-> file <-> testing -> NULL
,在word = c
之前添加包含c
a
的节点而不是a
,我遇到了问题在file
和"Add: Placing c before list head c"
之间。该函数打印c < a
,似乎正在评估a
。但即使评估不正确,我也不知道在进行任何节点操作之前它是如何替换NODES * arg
的。如果有人知道什么可能导致这个问题,我会很感激这个建议。附:传入arg -> next == NULL; arg -> prev == NULL; arg -> word != NULL;
始终采用list -> prev
的形式,但如果尚未添加任何节点,则列表可以将所有字段设为NULL,int addToList(struct NODES * list, struct NODES * arg){
fprintf(stderr,"Add: Adding %s\n", arg->word);
if(list->word == NULL){
list->word = (char *)malloc(strlen(arg->word));
strcpy(list->word, arg->word);
list->next = NULL;
list->prev = NULL;
fprintf(stderr,"Add: Head %s\n", list->word);
return 2;
}
struct NODES * abc = list;
while(abc->word != NULL){
if(strcmp(abc->word, arg->word)<0){
fprintf(stderr, "abc %s < arg %s", abc->word, arg->word);
if (abc->next != NULL)
abc = abc->next;
else{
abc->next = malloc(sizeof(NODE));
abc->next->prev = abc;
abc = abc->next;
abc->next = NULL;
abc->word = NULL;
}
}
else if(abc == list){
fprintf(stderr, "Add: Placing %s before list head %s\n", arg->word, list->word);
arg->next = list;
list->prev = arg;
arg->prev = NULL;
list = arg;
fprintf(stderr, "Add: Placed %s before %s\n", list->word, list->next->word);
return 3;
}
else{
fprintf(stderr, "Add: Placing %s between %s and %s\n", arg->word, abc->word, abc->next->word);
arg->next = abc;
arg->prev = abc->prev;
if(abc->prev != NULL)
abc->prev->next = arg;
abc->prev = arg;
fprintf(stderr, "Added %s after %s and before %s\n", arg->word, arg->prev, arg->next->word);
return 1;
}
}
abc->word = (char *)malloc(strlen(arg->word));
strcpy(abc->word, arg->word);
fprintf(stderr, "Added %s after %s and before %s\n", abc->word, abc->prev->word, abc->next);
return 1;
}
在调用函数时应始终为NULL该函数终止。
int addToList(struct NODES ** list, struct NODES * arg){
fprintf(stderr,"Add: Adding %s current head %s\n", arg -> word, (*list)->word);
if((*list) -> word == NULL){
(*list) -> word = malloc(strlen(arg->word)+1);
strcpy((*list) -> word, arg -> word);
(*list) -> next = NULL;
(*list) -> prev = NULL;
fprintf(stderr,"Add: Head %s\n", (*list) -> word);
return 2;
}
struct NODES * abc = (*list);
//while arg > abc
fprintf(stderr,"Comparing %s and %s\n", abc->word,arg->word);
while(strcmp(abc->word, arg->word)<0){
fprintf(stderr,"Comparing %s and %s\n", abc->word,arg->word);
if (abc -> next == NULL)
break;
abc = abc -> next;
}
if (abc == (*list)){
if(!(strcmp(abc->word, arg->word)<0)){
arg -> next = abc;
arg -> prev = NULL;
abc -> prev = arg;
*list = arg;
}
else{
abc -> next = arg;
arg -> prev = abc;
abc -> next = NULL;
}
return 5;
}
if(abc -> next != NULL){
fprintf(stderr, "Inserting %s between %s and %s\n", arg -> word, abc->prev->word,abc->word);
arg -> next = abc;
arg -> prev = abc -> prev;
arg -> prev -> next = arg;
abc -> prev = arg;
fprintf(stderr, "Added %s before %s and after %s\n", arg->word, arg->prev->word,arg->next->word);
return 3;
}
return 0
}
更新以反映建议:
{{1}}
答案 0 :(得分:1)
函数收到的list
参数是调用者具有的列表指针的副本。要返回修改后的列表指针,函数可能如下所示:
int addToList(struct NODES ** list, struct NODES * arg)
它将被称为这样的东西:
result = addToList(&list, arg);
该函数将提供一个像这样的新列表指针
*list = arg;
您目前拥有的所有列表访问权限都是间接的一步
if(list->word == NULL)
会变成
if((*list)->word == NULL)
<强>更新强>
尝试这个简化的代码,我发现这比让你的头脑更容易。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct NODES {
struct NODES *prev;
struct NODES *next;
char *word;
};
void showList(struct NODES * list) {
while (list) {
if (list->prev)
printf("%-10s", list->prev->word);
else
printf("%-10s", "NULL");
printf(" <- %-10s -> ", list->word);
if (list->next)
printf("%-10s", list->next->word);
else
printf("%-10s", "NULL");
printf("\n");
list = list->next;
}
}
int addToList(struct NODES ** list, char *word){
struct NODES *wptr, *lptr = *list, *pptr = NULL;
if ((wptr = malloc(sizeof(struct NODES))) == NULL)
return -1;
wptr->prev = NULL;
wptr->next = NULL;
if ((wptr->word = strdup(word)) == NULL)
return -2;
if (lptr == NULL) {
*list = wptr; // first list item
return 0;
}
while (lptr) {
if (strcmp(word, lptr->word) <= 0) {
wptr->next = lptr; // insert before current node
wptr->prev = pptr;
if (pptr)
pptr->next = wptr;
else
*list = wptr;
lptr->prev = wptr;
return 1;
}
pptr = lptr;
lptr = lptr->next;
}
wptr->prev = pptr; // insert at tail
pptr->next = wptr;
return 2;
}
int main()
{
struct NODES *list = NULL;
addToList(&list, "one");
addToList(&list, "two");
addToList(&list, "three");
addToList(&list, "four");
addToList(&list, "five");
showList(list);
return 0;
}
节目输出:
NULL <- five -> four
five <- four -> one
four <- one -> three
one <- three -> two
three <- two -> NULL
答案 1 :(得分:0)
我怀疑你的问题在这里:
list->word = (char *)malloc(strlen(arg->word));
strcpy(list->word, arg->word);
由于您没有为终止空字符分配空间,因此稍后对strcmp的调用将超出分配的缓冲区。这可能有各种各样的行为,很可能也是你看到的行为。
另外,drop the (char *)
cast,它可能会隐藏您的代码的其他问题。