首页 > 解决方案 > 将元素添加到 C 中链接列表的特定链接列表

问题描述

假设我们有以下结构:

typedef struct link {
    char link[MAXLINK];
    struct link *next;
} LinkT;

typedef struct node {
    char keyword[MAXKEY];
    LinkT *links;
    struct node *next; 
} NodeT;

在主要功能中,我添加了一些新关键字和指向它的链接。打印整个列表时得到的输出是:

Asteroid
    Link-45
    Link-23
Earth
    Link-2
Moon
    Link-3
    Link-1

我想向地球添加一个新的链接 4。所以输出看起来像这样:

Asteroid
    Link-45
    Link-23
Earth
    Link-2
    Link-4
Moon
    Link-3
    Link-1

我的想法是有一个findLink遍历关键字列表的函数,然后关键字匹配,遍历链接列表,如果没有找到链接,我添加一个新的。

但是,问题是当我运行下面的代码时,它永远不会完成,不输出任何东西(冻结?),我必须强制退出它。

如果我删除最后添加的关键字和链接,它会运行但不正确并打印该链接不在列表中。类似findKeyword的功能也一样 - 打印不在列表中的关键字。

如何修复代码以使其适用于任何列表?

代码:

NodeT *addNewKeyword(NodeT **list, char *keyword) {
    NodeT *new = malloc(sizeof(NodeT));
    assert(new != NULL);
    strcpy(new->keyword, keyword);
    new->next = *list;
    *list = new;
    return 0;
}

LinkT *addNewLink(NodeT *list, char *link) {
    LinkT *new = malloc(sizeof(LinkT));
    assert(new != NULL);
    strcpy(new->link, link);
    new->next = list->links;
    list->links = new;
    return 0;
}

NodeT *findKeyword(NodeT *list, char *keyword) {
    NodeT *current = list;
    while (current != NULL) {
        if (strcmp(current->keyword, keyword) == 0) {
            return current;
        }
        current = current->next;
    }
    return NULL;
}

void *findLink (NodeT *list, char *keyword, char *link) {
    NodeT *current = list;
    while (current != NULL) {
        if (strcmp(current->keyword, keyword) == 0) {
            
            LinkT *currentLink = list->links;

            while (currentLink != NULL) {
                if (strcmp(currentLink->link, link) == 0) {
                    return currentLink;
                }
                currentLink = list->links->next;
            }
            return NULL;
        }
        current = current->next;
    }
    return NULL;
}

void *printList(NodeT *listNode) {
    while (listNode != NULL) {
        printf("%s\n", listNode->keyword);

        LinkT *listLink = listNode->links;
        if (listLink == NULL) {
            printf("List is empty.\n");
        } else {
            while (listLink != NULL) {
                printf("    %s\n", listLink->url);
                listLink = listLink->next;
            }
        }
        listNode = listNode->next;
    }
    return 0;
}

int main() {

    NodeT *wordsList = NULL; 

    addNewKeyword(&wordsList, "Moon");
    addNewLink(wordsList, "Link-1");
    addNewLink(wordsList, "Link-3");

    addNewKeyword(&wordsList, "Earth");
    addNewLink(wordsList, "Link-2");
    
    /* runs after removing following lines: */
    // addNewKeyword(&wordsList, "Asteroid");
    // addNewLink(wordsList, "Link-23");
    // addNewLink(wordsList, "Link-45");

    if (findKeyword(wordsList, "Moon") == 0) {
        printf("Keyword is in list.\n");
    } else {
        printf("Keyword is not in list.\n");
    }

    if (findLink(wordsList, "Moon", "Link-1") == NULL) {
        printf("Link is not in list.\n");
        addNewLink(wordsList, "Link-1");
    } else {
        printf("Link is in list.\n");
    }

    printList(wordsList);

    return 0;
}

编辑 1

我正在从函数类型 void 返回一个节点,这可能是无法按预期工作的原因。findLink功能需要是什么类型?

编辑 2

正如 Sahin 在回答中指出的那样,我更新了findLink函数,现在程序运行了,但是在不正确的位置添加了一个元素。主代码变化:

int main() {
    ...
    addNewKeyword(&wordsList, "Moon");
    addNewLink(wordsList, "Link-1");
    addNewLink(wordsList, "Link-3");

    addNewKeyword(&wordsList, "Earth");
    addNewLink(wordsList, "Link-2");
    
    addNewKeyword(&wordsList, "Asteroid");
    addNewLink(wordsList, "Link-23");
    addNewLink(wordsList, "Link-45");

    if (findLink(wordsList, "Earth", "Link-4") == NULL) {
        printf("Link is not in list.\n");
        addNewLink(wordsList, "Link-4");
    } else {
        printf("Link is in list.\n");
    }
    ...
}

输出:

Link is not in list.
Asteroid
    Link-4
    Link-45
    Link-23
Earth
    Link-2
Moon
    Link-3
    Link-1

标签: c

解决方案


void *findLink (NodeT *list, char *keyword, char *link) {
    NodeT *current = list;
    while (current != NULL) {
        if (strcmp(current->keyword, keyword) == 0) {
            
            LinkT *currentLink = current->links;//An error is here, you always look for the same list.

            while (currentLink != NULL) {
                if (strcmp(currentLink->link, link) == 0) {
                    return currentLink;
                }
                currentLink = currentLink->next;//The other error is here
            }
            return NULL;
        }
        current = current->next;
    }
    return NULL;
}

我猜你的错误就在这里,你需要获取 currentLink 的下一个,因为同一个节点的下一个总是相同的。完成这些更正后,您需要测试代码,然后我们可以再次查看结果。

编辑:响应编辑2:

NodeT *addNewKeyword(NodeT **list, char *keyword) {
    NodeT *new = malloc(sizeof(NodeT));
    assert(new != NULL);
    strcpy(new->keyword, keyword);
    new->next = *list;
    *list = new; //This row
    return 0;
}

在我发表评论的行中,您更改了参数内的值,并且列表变量中的值发生了变化。由于您最后使用“Asteroid”调用 addNeKeyword,因此会将新链接添加到那里。所以,请详细说明。你真正想要的是什么?


推荐阅读