c - 链表中的全局指针

标签 c linked-list dynamic-data singly-linked-list

所以我遇到了这个问题,我希望你能帮助我解决这个问题。我有这个链接列表,要求用户在其中输入数据。它适用于我只使用一组但我希望此链表适用于多于一组的情况,但我已将头节点声明为全局节点,但我不知道如何排列它。问题是,当我在一组中输入数据时,它也会为第二组保留该输入。

这是链表的结构:

struct node//initializing a linked list
{
    int info;
    struct node*link;
}*start;

这就是我创建链接列表的方式:

list* createList()
{
    struct node*set;
    set=(struct node*)malloc(sizeof(struct node));
    if(start==NULL)
    {
        set->link=NULL;
        start=set;
    }
    return set;
} 

最后这是添加函数:

list* Add(list* set,int x)
{
    struct node *tempnode;
    if(start==NULL)
    {
        printf("Memory Allocation failed. Goodbye!");
    exit(EXIT_FAILURE);
    }
    set=start;
    printf("Please enter an input: \n");
    scanf("%d",&x);
    while(1)
    {
        while(x==set->info)
        {
            printf("Error! Please enter another integer: \n");
            scanf("%d",&x);
            set=start;
        }
        if(set->link!=NULL)
        set=set->link;
        else
            break;
    }
    tempnode=(struct node*)malloc(sizeof(struct node));
    tempnode->info=x;
    tempnode->link=NULL;
    set->link=tempnode;
    printf("%d was created successfully!\n",x);
    return set;
}

最佳答案

正如 Oli Charlesworth 已经评论的那样,您需要将要操作的列表作为参数传递给每个处理列表的函数。我将立即向您展示如何操作,但首先让我评论一下您的代码的一些问题。

  • 您的代码看起来不整洁,因为您没有分离 设置(添加号码,检查号码是否已在集合中) 输入(与 scanf 相关的所有内容)。相反,您使用 Add 函数 在一个大块中实现所有内容。

  • 此外,为什么要将 x 作为参数传递给 Add?从来没有读过 (至少在被 scanf 覆盖之后)。这确实应该 是一个局部变量。 set 也是如此,您将其用作本地 目前存在变量。

  • 您已经 typedef'fed struct nodelist,这是合法的, 但有点令人困惑。 (节点不是列表。)

好的,继续回答你的问题:你应该为每个新列表创建一个 start = NULL 。然后将 start 传递给所有列表函数。但这里您必须小心:大多数功能(例如打印或检查数字是否在列表中)不会更改 start 的值。您添加的函数必须更改它,因此您应该将 &start(即 struct node **)传递给此类函数。

因为这有点令人困惑,您可以使用替代解决方案:创建一个表示列表的结构,为该列表编写一个创建者函数,然后对该结构的指针进行操作。

这是一个示例实现:

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

typedef struct Set Set;
typedef struct Node Node;

struct Node {
    int info;
    Node *next;
};

struct Set {
    Node *head;
};

Set *set_create()
{
    Set *set = malloc(sizeof(*set));

    // enforce set != NULL
    set->head = NULL;
    return set;
}

void set_delete(Set *set)
{
    Node *node = set->head;

    while (node) {
        Node *next = node->next;
        free(node);
        node = next;
    }
}

int set_contains(const Set *set, int x)
{
    const Node *node = set->head;

    while (node) {
        if (node->info == x) return 1;
        node = node->next;
    }

    return 0;
}

void set_print(const Set *set)
{
    const Node *node = set->head;

    printf("{");
    while (node) {
        if (node != set->head) printf(", ");
        printf("%d", node->info);
        node = node->next;
    }
    printf("}\n");
}

Node *set_add(Set *set, int x)
{
    Node *node;

    if (set_contains(set, x)) return NULL;

    node = malloc(sizeof(*node));
    // enforce node != NULL

    node->info = x;
    node->next = NULL;

    if (set->head == NULL) {
        set->head = node;
    } else {
        Node *iter = set->head;

        while (iter->next) iter = iter->next;
        iter->next = node;
    }

    return node;
}

int main()
{
    Set *one = set_create();
    Set *two = set_create();

    set_add(one, 1);
    set_add(one, 1);
    set_add(one, 2);
    set_add(one, 3);
    set_add(one, 5);
    set_add(one, 1);
    set_add(one, 5);

    set_add(two, 1);
    set_add(two, 2);
    set_add(two, 4);

    set_print(one);
    set_print(two);

    set_delete(one);
    set_delete(two);

    return 0;
}

有几点需要注意:

  • 代码被分成执行特定任务的小函数。他们可能会互相打电话,所做的事情总是很清楚。

  • 构造函数set_create创建一个指向空列表的指针。该指针是您的句柄,您应该将其作为第一个参数传递给所有列表函数。

  • 如代码中所示,添加整数的函数会检查列表是否已包含该整数。然而,由于 set_add 函数不处理来自用户的输入,因此它会在其返回值中表明节点是否确实已添加:如果整数已经在列表中,否则是指向新节点的指针。

  • 当您创建一个列表并向其中添加整数时,您可以使用 malloc 分配内存。这意味着,您还需要有一个使用 free 再次释放内存的函数,这样就可以避免内存泄漏。

  • 示例代码将一些硬连线整数添加到列表中;它不处理用户输入。您可以轻松编写一个循环来在 main 函数中添加元素,然后添加它们。

  • 由于列表的句柄是一个结构,因此您可以通过向该结构添加新字段来轻松扩展列表接口(interface)。例如,您可能想要保留节点计数或指示节点是否已排序的标志。

关于c - 链表中的全局指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20932623/

相关文章:

管脚映射代码

c - 将不同大小的纹理附加到 FBO 的问题

c - 使用 WM_NCHITTEST 时捕获鼠标左键时出现问题

c++ - 在 C++ 中从堆栈中弹出一个数字?

asp.net - VS 2010 中缺少 App_Code 文件夹

c - 应用于字符串数组指针的逻辑

java - 删除索引 N 处的元素,LinkedList

java - 从父类(super class) : Node to SpecialNode in a linked list 向下转型

c# - 如何在 C# 中动态命名变量?

linq - 使用 Linq 连接动态数据表