【问题标题】:linked list of strings in CC中的字符串链表
【发布时间】:2016-07-23 12:49:54
【问题描述】:

我正在尝试在 C 中创建一个字符串链接列表,但在将第一个节点添加到列表中时遇到了问题。无论出于何种原因,即使我将 head 变量引用到 newNode,我的程序也会打印 NULL,但它不会将字符串从 struct 指针复制到 struct 指针。任何帮助表示赞赏。谢谢!

#include "stdafx.h"
#include <stdlib.h>
#include <string.h>

typedef struct stringData {
    char *s;
    struct stringData *next;
} Node;

Node *createNode(char *s) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->s = s;
    newNode->next = NULL;
    return newNode;
}


void insert(Node *head, Node *newNode) {
    if (head == NULL) {
        head->s = newNode->s;
        head = newNode;
    }
}

void printList(Node *head) {
    while (head != NULL) {
        printf("%s\n", head->s);
        head = head->next;
    }
}



int main()
{
    Node *head = createNode(NULL);

    Node *a = createNode("A");
    insert(head, a);

    printList(head);
    return 0;
}

【问题讨论】:

  • if (head == NULL) {head-&gt;s = newNode-&gt;s; 指针不能这样工作。如果head 没有指向任何东西,你就不能碰head-&gt;anything,它不存在。
  • 所有其他链表帖子(有数千个)都有“仅修改本地头部”错误:(
  • 由于您的代码不正确,不清楚您是将新节点插入到列表的开头还是列表的末尾。如果您将新节点插入到列表的开头,printList 将按照它们插入的相反顺序(LIFO 顺序)打印字符串。如果您将新节点插入到列表的末尾,printList 将按照它们插入的顺序(FIFO 顺序)打印字符串。对于(单个)链表的 LIFO 排序,通常有一个变量指向链表的第一个(头)节点,另一个变量指向最后一个(尾)节点。

标签: c memory-management data-structures linked-list malloc


【解决方案1】:

这是代码的修改版本,它给出了在列表开头和结尾插入新节点的示例。事实上,insert 函数可用于在列表中的任何位置插入一个新节点,因为它只需要一个指向链接的指针和一个指向要插入的节点的指针。

#include <stdlib.h>
#include <stdio.h>

typedef struct stringData {
    char *s;
    struct stringData *next;
} Node;

Node *createNode(char *s) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->s = s;
    newNode->next = NULL;
    return newNode;
}


void insert(Node **link, Node *newNode) {
    newNode->next = *link;
    *link = newNode;
}

void printList(Node *head) {
    while (head != NULL) {
        printf("%s\n", head->s);
        head = head->next;
    }
}



int main(void)
{
    Node *head = NULL;
    Node *tail = NULL;
    Node *n;

    n = createNode("B");
    // First node at start of list - head is updated.
    insert(&head, n);
    // First node is also the tail.
    tail = n;

    n = createNode("A");
    // Insert node at start of list - head is updated.
    insert(&head, n);

    n = createNode("C");
    // Insert node at end of list.
    insert(&tail->next, n);
    // Update tail.
    tail = n;

    printList(head);
    return 0;
}

【讨论】:

    【解决方案2】:

    下面的代码sn-p是错误的:

    void insert(Node *head, Node *newNode) {...}
    ...
    insert(head, a);
    

    您需要通过引用传递指针。目前您正在更改本地副本(参数)。

    修复
    将您的insert 更改为:

    void insert(Node **head, Node *newNode) {...}
    

    并调用为:

    insert(&head, a);
    

    还有什么
    至少insert(并且可能)更多的功能不是万无一失的(保证空指针取消引用,else 大小写未处理等)。您需要调试和修复许多此类情况。在编码之前在纸上正确地使用您的方法可能会有所帮助。

    【讨论】:

    • 上升了。我同意,但该功能需要做的工作远不止这些。它直接取消引用现在的 NULL 指针,并且在非 null 时什么也不做(有或没有传递引用的解决方案)。
    • @WhozCraig 对,订单不好,else 案例的处理缺失。但是后来我想提示 OP 并帮助他修复代码而不是修复代码。但是,是的。我会在回答中提到这一点。
    • 我认为这根本不是意图。这只是一个糟糕的参数名称“head”。他不想修改head——这是一个虚拟头部列表,他打算修改head-&gt;next
    • @paddy 那么head = newNode;的目的是什么?
    • 我确定他们的意思是head-&gt;next = newNode。但也许你是对的。也许它只是看起来像一个傻瓜列表,而实际上它是你所想的。代码可以采用任何一种方式。 printList 函数表明它不是假头。 insert 函数显示完全不了解任何一种列表样式。
    猜你喜欢
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多