【问题标题】:Difference between Node->next!=NULL and Node!=NULL in CC 中 Node->next!=NULL 和 Node!=NULL 之间的区别
【发布时间】:2018-07-07 17:14:23
【问题描述】:

如果我在while 条件下进行修改并将temp != NULL 更改为temp->next = NULL,则此功能不起作用。这是为什么呢?

void Print() {
     printf("\n");
     printf("The Library data is as follows: \n");
     struct Node *temp = head; // where head is a global variable
     printf("\n");
     while (temp != NULL) {
         printf("%25s", temp->name);
         printf("%25s", temp->author);
         temp = temp->next;
         printf("\n");
     }
}

另外,如果我修改else 块下的while 循环条件,从temp1->next = NULLtemp1 != NULL,它不起作用。这是为什么呢?

void Insert(char q[50], char r[50]) {
    struct Node *temp = (struct Node*)malloc(sizeof(struct Node));
    temp->next = NULL; // Since we are adding a node to the end, we are linking it to NULL.
    strcpy(temp->name, q); // copying the contents of "q" to "temp->name"
    strcpy(temp->author, r); // same
    if (head == NULL) {
        head = temp;
    } else {
        struct Node *temp1 = head;
        while (temp1->next != NULL)
            temp1 = temp1->next;
        temp1->next = temp;
    }
}

【问题讨论】:

  • 因为temp 可能是NULL。您必须在取消引用它之前建立它。如果是,则您已到达链表的末尾。顺便说一句,您通常将一个项目添加到链表的 head,而不是尾部。
  • 因为编写的代码表达了用于迭代/扩展链表的正确算法,而您的更改表达了不正确的算法。我建议您花一些时间使用白板:[a]->[b]->[c]->null。迭代到列表的末尾,这样你就有了 {c,null},然后用 {d,null} 扩展它并考虑它。另一个很好的练习是制定如何从列表中删除节点 b 的详细信息。
  • 如果您将布尔表达式 temp- != NULL 更改为赋值 temp->next = NULL,则可能会发生两件事:a) temp 最初是 NULL,并且您有一个空指针取消引用;或 b) temp->next 更改为 NULL 并且由于这是一个 false-y 值,因此永远不会执行循环。

标签: c linked-list nodes


【解决方案1】:

Print 函数中,您想枚举列表中的所有节点,并且您想优雅地处理一个空列表(head = NULL)。因此循环迭代while (temp == NULL)temp 跳到具有temp = temp->next; 的下一个节点。

Insert 函数中,分配并初始化了一个新节点。空列表 (head == NULL) 有一个特殊情况,其中head 只接收指向新节点的指针。相反,如果列表不为空,您希望通过将其next 指针指向新节点来查找列表的last 节点以追加新节点。循环从第一个节点迭代到最后一个节点,如果节点不是最后一个节点,则测试 temp1->next != NULL 成功。因此temp 指向while 循环之后的最后一个节点,新节点可以简单地附加temp1->next = temp;

注意以下备注:

  • 原型void Insert(char q[50], char r[50]) 应该改进为int Insert(const char *name, const char *author),因为:
    • 作为参数传递的字符串不会被函数修改
    • 参数名称会更清晰
    • 编译器会忽略指定的数组大小,并且看起来与实际的结构成员不一致。
    • 函数可能会失败。它至少应该返回一个成功指示符。
  • 应测试内存分配是否成功,应报告失败
  • 如果参数字符串太长,strcpy 将导致未定义的行为。
  • malloc 的返回值无需在 C 中强制转换。

这是一个改进的版本:

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

struct Node {
    char name[50];
    char author[50];
    struct Node *next;
};

struct Node *head = NULL;

void Print(void) {
     printf("\nThe Library data is as follows:\n\n");
     struct Node *temp = head; // where head is a global variable
     while (temp != NULL) {
         printf("%25s  %-25s\n", temp->name, temp->author);
         temp = temp->next;
     }
}

int Insert(const char *name, const char *author) {
    struct Node *temp = malloc(sizeof(struct Node));
    if (temp == NULL)
        return -1;
    temp->next = NULL;
    snprintf(temp->name, sizeof(temp->name), "%s", name);
    snprintf(temp->author, sizeof(temp->author), "%s", author);

    if (head == NULL) {
        head = temp;
    } else {
        struct Node *temp1 = head;
        while (temp1->next != NULL)
            temp1 = temp1->next;
        temp1->next = temp;
    }
    return 0;
}

int main() {
    if (Insert("Flowers for Algernon", "Daniel Keyes")
    ||  Insert("Blade Runner", "Philip K. Dick")
    ||  Insert("2001, a Space Odyssey", "Arthur C. Clarke")) {
        printf("out of memory\n");
        return 1;
    }
    Print();
    return 0;
}

【讨论】:

    【解决方案2】:

    当在 while 循环中将其更改为 node->next 时,这意味着此循环循环,而 node->next 为空,因此您错过了链接数组的最后一个节点,因为该节点的-next 为空,因此这次循环中断。并且只将 temp 写入您的 while u 不需要 temp != NULL 当 temp 为 null 时,此循环会中断,所以只放

    while(temp){
    //your code
    }
    

    我希望这会对你有所帮助。 :-)

    【讨论】:

      【解决方案3】:

      在第一种情况下,您正在遍历整个链表。链表的末尾由 NULL 指针表示,根据您的代码,因此使用 while(temp!=NULL)。如果有超过2 个节点,跳过最后一个。

      在第二种情况下,您将新节点添加到最后一个节点的末尾。因此您必须使用temp1-&gt;next!=NULL。这样最后一个节点的next指针就可以指向新添加的节点。如果在这种情况下使用temp!=NULL,那么temp就变成NULL。所以下一条语句temp1-&gt;next=temp; 不起作用。

      • 如果您在第一种情况下进行更改,只会导致程序跳过 打印链表中的最后一个节点。

      • 如果您在第二种情况下进行更改,这将导致您的代码获取 终止(runtime error)

      【讨论】:

        【解决方案4】:

        很简单

        1. 在函数print() 中使用while(temp-&gt;next!=null) 时不会最后打印 节点,因为当指针 temp 位于最后节点时,节点 temp-&gt;next 为空且 while 条件 变为 false 并退出 while 循环。
        2. 在函数insert() 中如果你将while(temp1-&gt;next!=NULL) 更改为while(temp1!=NULL) 那么 当它来自 while 循环 temp1 指向 null 时意味着没有分配内存。 因此在 while 循环之后写入 temp1->next 会显示错误为 you cannot excess next part of temp because memory is not allocated

        希望对您有所帮助!

        【讨论】:

          猜你喜欢
          • 2020-08-12
          • 1970-01-01
          • 2023-03-06
          • 1970-01-01
          • 2012-09-03
          • 1970-01-01
          • 2013-01-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多