【问题标题】:Adding an element to beginning of linked list C将元素添加到链表 C 的开头
【发布时间】:2021-04-16 09:16:23
【问题描述】:

我是编程新手,目前正试图找出 C 中的链表。我创建了一个简单的列表,其中包含三个节点,其中包含数字 1、2 和 3。

typedef struct Node {
    int data;
    struct Node* next;
} Node;

int main() {
    struct Node* head = NULL;
    struct Node* second = NULL;
    struct Node* third = NULL;

    head = (struct Node*)malloc(sizeof(struct Node));
    second = (struct Node*)malloc(sizeof(struct Node));
    third = (struct Node*)malloc(sizeof(struct Node));

    head->data = 1; // assign data in first node
    head->next = second; // Link first node with second node

    second->data = 2; // assign data to second node
    second->next = third;// Link second node with the third node

    third->data = 3; // assign data to third node
    third->next = NULL;
}

接下来我想使用 add_and_print 函数将用户输入的值插入到列表的开头

int num;
printf("Enter number to add to beginning of list: ");
scanf(" %d", &num);

add_and_print(num, head);

函数 add_and_print 如下所示:

void add_and_print(int num, Node* head) {
    Node* new_node;
    new_node = (Node*)malloc(sizeof(struct Node));
    new_node->data = num;
    new_node->next= head;
    head = new_node;
    printf("Value inside Function: %d\n", head->data);

}

对于“函数内部的值”,我得到了我之前输入的值,到目前为止一切都很好。但是,在 main 中调用该函数后,我尝试再次打印 head 值

add_and_print(num, head);
printf("Value outside function: %d", head->data);

我得到 1,即应用该函数之前的头部值。当我尝试打印整个列表时,我得到 123。我不明白为什么函数所做的更改没有全局保存。

提前谢谢你:)

【问题讨论】:

  • 请阅读linked lists 上的维基百科页面。那里有一个漂亮的身影。然后阅读您的编译器(例如GCC,您可以调用为gcc -Wall -Wextra -g)和调试器(例如GDB)的文档
  • 考虑从add_and_print 函数返回new_node。您可以将此值分配给head...

标签: c linked-list pass-by-reference singly-linked-list function-definition


【解决方案1】:

函数参数是函数的局部变量,由用作参数的表达式的值初始化。

因此,在您的函数add_and_print 中,您正在处理函数局部变量head,该变量由main 中声明的指针head 的值初始化。更改函数内的局部变量(参数)head 不会影响原始参数。

您必须通过引用传递在main 中声明的指针head。在 C 中,通过引用传递意味着通过指向对象的指针间接传递对象。

函数可以通过以下方式声明和定义。

int add_and_print( Node **head, int num ) 
{
    Node *new_node = malloc( sizeof( struct Node ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->data = num;
        new_node->next = *head;
        *head = new_node;
        printf( "Value inside Function: %d\n", head->data );
    }
    else
    {
        puts( "Error. Not enough memory." );
    }

    return success;
}

并且可以像这样调用该函数

if ( add_and_print( &head, num ) )
{
    printf( "Value outside function: %d\n", head->data );
}

注意该函数不应输出任何消息。函数的调用者决定是否输出消息。所以最好像这样定义函数

int add_front( Node **head, int num ) 
{
    Node *new_node = malloc( sizeof( struct Node ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->data = num;
        new_node->next = *head;
        *head = new_node;
    }

    return success;
}

在 main 你可以写

if ( add_front( &head, num ) )
{
    printf("Value outside function: %d\n", head->data);
}
else
{
    puts( "Error. Not enough memory." );
}

【讨论】:

    【解决方案2】:

    您的调用函数不会看到您进行更改的方式,因为更改是 add_and_print 本地的。

    你的add_and_print应该是这样的:

    要么遵循案例 1:
    head的地址传递为add_and_print(num, &head)

    void add_and_print(int num, Node** head) {
        Node* new_node;
        new_node = (Node*)malloc(sizeof(struct Node));
        new_node->data = num;
        new_node->next= *head;
        *head = new_node;
        printf("Value inside Function: %d\n", head->data);
    
    }
    

    或遵循案例2:
    head附加到新节点后返回新节点地址

    head = add_and_print(num, head)

    Node* add_and_print(int num, Node* head) {
        Node* new_node;
        new_node = (Node*)malloc(sizeof(struct Node));
        new_node->data = num;
        new_node->next= head;
        printf("Value inside Function: %d\n", head->data);
        return new_node;
    }
    

    注意:使用前检查malloc返回值,使用完后检查free指针。

    【讨论】:

      【解决方案3】:

      main 中的head 变量和add_and_printhead 参数是两个不同的变量。所以add_and_print 中的赋值head = new_node不会更新main 中的head 变量。

      更新main 中的head 变量并在那里更新它的唯一方法是从add_and_print 函数返回新值:

      Node* add_and_print(int num, Node* head) {
          Node* new_node;
          new_node = (Node*)malloc(sizeof(struct Node));
          if (new_node) {
              new_node->data = num;
              new_node->next= head;
              head = new_node;
              printf("Value inside Function: %d\n", head->data);
          }
          return head;
      }
      

      main 内部调用这个为

      head = add_and_print(num, head);
      

      请注意,我添加了最少量的错误检查,add_and_print 永远不会返回 NULL(并且无法报告错误)

      顺便说一句,让函数执行多项操作通常不是一个好主意。这里的打印可能有助于调试,但不应该是最终功能的一部分。当它在 from 中添加一个项目时,您可以将其命名为 add_to_frontprepend

      【讨论】:

      • 声称“唯一的方法”是夸大了你的情况。还有另一种实现结果的方法(那些绝望的人可能会尝试修改全局变量,但这不是一个好主意)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-23
      • 2021-06-28
      • 2013-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多