繁体   English   中英

我的功能没有记住链接列表的开头

[英]My function doesn't memorize the head of linked list

我必须做一个具有很多功能的链表程序,例如删除,添加和修改号码。

在我的代码中,当我在函数中选择数字1时,在此之后,当我想显示所有数字时,我将head放在参数中,但是我在Visual Studio中看到函数的参数没有任何内容。 为了在函数Displaynbr中的参数中传递链接列表的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);
    }
}

您离它不是很远,但是忘记了一条基本规则: 当您更改函数中参数的值时,调用者的值保持不变

因此, 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一样将其返回给调用方,也可以使用双倍间接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;
}

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

该函数具有一个原型

Mynbr* Addnumber(Mynbr* first)

它由Addnumber(first)调用。 通常,由于函数的变化, 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建议添加到列表的head_nbr 要最后添加,您将必须进行适当的修改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM