我的功能并没有记住链表的头部

时间:2016-06-08 11:17:26

标签: c linked-list

我必须做一个链接列表的程序,其中包含许多功能,如删除,添加和修改数字。

在我的代码中,当我在我的函数中添加一个数字时,选择1,之后当我想显示所有数字时,我把头放在参数中,但我在visual studio中看到函数的参数不在&#39什么都没有。如何在函数Displaynbr

中的参数中传递链表的头部,我该怎么办?
#include <stdio.h>
#include <stdlib.h>

struct Mynbr
{
    int nbr;
    struct Mynbr* next;
} typedef Mynbr;

void Menu();
void choiceMenu(int choice, Mynbr* first);
Mynbr* Addnumber(Mynbr* first);
void Displaynbr(Mynbr* first);

int main(void)
{
    Mynbr* head = NULL;
    int choice = 0;

    while (choice!=5)
    {
        Menu();
        printf("Your choice : "); scanf("%d", &choice);
        choiceMenu(choice, head);
    }
    system("PAUSE");
    return 0;
}

void Menu()
{
    printf("\n1.Add number to the list\n");
    printf("2.Delete number from the list\n");
    printf("3.Search number in the list\n");
    printf("4.Display all the numbers from the list\n");
    printf("5.Exit\n");
}

void choiceMenu(int choice, Mynbr* first)
{
    switch (choice)
    {
    case 1:
        Addnumber(first);
        break;
    case 2:
        break;
    case 3:
        break;
    case 4:
        Displaynbr(first);
        break;
    case 5:
        break;
    }
}

Mynbr* Addnumber(Mynbr* first)
{
    printf("\n===Function to add a number===\n");
    Mynbr* head_nbr = first;
    if (!head_nbr)
    {
        head_nbr = (Mynbr*)malloc(sizeof(Mynbr));
        printf("Enter a number :"); scanf("%d", &(head_nbr->nbr));
        head_nbr->next = NULL;
    }
    return head_nbr;
}

void Displaynbr(Mynbr* first)
{
    printf("\n===Function to display number===\n");
    Mynbr* curr = first;
    if (curr->next)
    {
        printf("The number is : %d", curr->nbr);
        Displaynbr(first->next);
    }
}

2 个答案:

答案 0 :(得分:1)

你离它不远,但忘记了一条基本规则: 当您更改某个功能中参数的值时,来电者的值保持不变

所以AddNumber(差不多)正确地返回列表头地址的新值,但choiceMenu会立即丢弃它。

所以这里有一些修正:

AddNumber应该可以在空列表或非空列表中添加一个数字(注意:它目前会导致LIFO):

Mynbr* Addnumber(Mynbr* first){
    printf("\n===Function to add a number===\n");
    Mynbr* head_nbr = first;
    head_nbr = (Mynbr*)malloc(sizeof(Mynbr));
    printf("Enter a number :"); scanf("%d", &(head_nbr->nbr));
    head_nbr->next = first;   // just link to initial head, be it null or not

    return head_nbr;
}

choiceMenu不应丢弃新头 - 您可以像调用AddNumber一样将其返回给调用者,也可以使用双重间接:

void choiceMenu(int choice, Mynbr** first){
    switch (choice){
case 1:
    *first = Addnumber(*first);
    break;

case 2:
    break;
case 3:
    break;
case 4:
    Displaynbr(*first);
    break;
case 5:
    break;
    }
}

(不要忘记更改初始声明并将其命名为:choiceMenu(choice, &head)

最后但并非最不重要的是,DisplayNumber错误地测试curr->next而不是curr

void Displaynbr(Mynbr* first){
    printf("\n===Function to display number===\n");
    Mynbr* curr = first;
    if (curr) {
        printf("The number is : %d", curr->nbr);
        Displaynbr(first->next);
    }
}

但仍会显示 ===功能,以显示列表中每个值的数字=== 。这里使用简单的迭代而不是递归更好:

void Displaynbr(Mynbr* first){
    printf("\n===Function to display number===\n");
    Mynbr* curr = first;
    while (curr) {
        printf("The number is : %d\n", curr->nbr);
        curr = curr->next;
    }
}

或使用for循环:

void Displaynbr(Mynbr* first){
    printf("\n===Function to display number===\n");
    Mynbr* curr;
    for (curr=first; curr != NULL; curr=curr->next) {
        printf("The number is : %d\n", curr->nbr);
    }
}

递归版本甚至可以通过删除无用的局部变量来更简洁(感谢@sokkyoku的提示):

void Displaynbr(Mynbr* first){
    printf("\n===Function to display number===\n");
    if (first) {
        printf("The number is : %d", first->nbr);
        Displaynbr(first->next);
    }
}

如果要将AddNumber更改为具有FIFO列表,则需要在列表末尾添加新元素。代码变为:

Mynbr* Addnumber(Mynbr* first){
    printf("\n===Function to add a number===\n");
    Mynbr* head_nbr = malloc(sizeof(Mynbr));
    printf("Enter a number :"); scanf("%d", &(head_nbr->nbr));
    head_nbr->next = NULL;
    if (first == NULL) first = head_nbr;
    else {
        Mynbr* last = first;
        while (last->next != NULL) last = last->next;
        last->next = head_nbr;
    }
    return first;
}

但是在这种情况下保持指向列表最后一个元素的指针而不是浏览列表来找到它会更有效。

答案 1 :(得分:0)

该函数有

的原型
Mynbr* Addnumber(Mynbr* first)

主要由Addnumber(first)调用。在main中,由于函数的更改,first指针指向的值将更新。但是,第一个指针本身不会更新。即指针将保持为NULL。如果它之前是NULL。

要修复此问题,您需要像这样调用main函数

first = Addnumber(first);

此外,您的AddNumber功能需要修复。对于列表的第二个或更大的元素,您不是在添加数字。

Mynbr* Addnumber(Mynbr* first){
  printf("\n===Function to add a number===\n");
  Mynbr* head_nbr;
  head_nbr = malloc(sizeof(Mynbr));
  printf("Enter a number :"); scanf("%d", &(head_nbr->nbr));
  if (!first)
  {
    head_nbr->next = NULL;
  }
  else
  {
    head_nbr->next = first;
  }
  return head_nbr;
}

此函数按变量head_nbr的建议添加到列表的开头。要在最后添加,您必须进行适当的修改。