【问题标题】:LinkedList length, access and implementation via a heap. CLinkedList 长度、访问和通过堆实现。 C
【发布时间】:2018-08-16 13:47:17
【问题描述】:

我正在尝试从 main.c 文件打印我在另一个名为 linklist.c 的 .c 文件中创建的链表的长度。它不起作用,我相信这与指针和/或内存管理有关。我主要在这里质疑堆。一些指导将不胜感激。

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

int main()
{
    printf("Hello world!\n");

    struct node* mylist = BuildOneTwoThree();
    int length = Length(mylist);

    printf(mylist->data);
    printf(length);
    return 0;
}

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


// Return the number of nodes in a list (while-loop version)
int Length(struct node** head) {
   int count = 0;
   struct node* current = head;
   while (current != NULL) {
      count++;
      current = current->next;
   }
   return(count);
}

/*
 Build the list {1, 2, 3} in the heap and store
 its head pointer in a local stack variable.
 Returns the head pointer to the caller.
*/
struct node* BuildOneTwoThree() {
   struct node* head = NULL;
   struct node* second = NULL;
   struct node* third = NULL;
   head = malloc(sizeof(struct node)); // allocate 3 nodes in the heap
   second = malloc(sizeof(struct node));
   third = malloc(sizeof(struct node));
   head->data = 1; // setup first node
   head->next = second; // note: pointer assignment rule
   second->data = 2; // setup second node
   second->next = third;
   third->data = 3; // setup third link
   third->next = NULL;
   // At this point, the linked list referenced by "head"
   // matches the list in the drawing.
   return head;
}

/*
 Takes a list and a data value.
 Creates a new link with the given data and pushes
 it onto the front of the list.
 The list is not passed in by its head pointer.
 Instead the list is passed in as a "reference" pointer
 to the head pointer -- this allows us
 to modify the caller's memory.
*/
void Push(struct node** headRef, int data) {
   struct node* newNode = malloc(sizeof(struct node));
   newNode->data = data;
   newNode->next = *headRef; // The '*' to dereferences back to the real head
   *headRef = newNode; // ditto head points to new node
}

// Given a list and an index, return the data
// in the nth node of the list. The nodes are numbered from 0.
// Assert fails if the index is invalid (outside 0..lengh-1).
int GetNth(struct node* head, int index) {
    struct node* current = head;
    int answer = 0;
    int x = index;
    if(x <= 0 || x >= sizeof(head)-1 )
        {
            return -1;
        }
    for(int i = 0; i <= sizeof(head)-1; i++){
        if (i == x){
            return current->data;
        }
        current = current->next;
    }
}

如您所见,我使用 BuildOneTwoThree 函数来构建链接列表并正在编写适当的函数...当我尝试将 mylist 访问到输出时它崩溃了。

【问题讨论】:

  • 你认为sizeof(head)会是什么?
  • 您的Length 函数将其参数声明为struct node **,但随后将其用作struct node *。你应该解决这个问题,但它可能不是问题的根源,因为实际参数匹配函数的实现而不是它的声明。
  • 是的,我看到我把它改回 struct node*。那是来自以前的故障排除,我认为错误是我试图将指针传递给指针。 @JohnBollinger
  • printf() 将格式字符串作为其第一个参数。相反,您传递的是普通的ints。由此产生的行为是未定义的,在实践中极不可能是你想要的......
  • 欢迎来到 Stack Overflow!请edit你的问题告诉我们你做了什么样的调试。我希望您已经在 Valgrind 或类似的检查器中运行了您的minimal reproducible example,并使用诸如 GDB 之类的调试器进行了调查。确保您也启用了全套编译器警告。这些工具告诉了你什么,它们缺少什么信息?并阅读 Eric Lippert 的 How to debug small programs

标签: c pointers data-structures struct nodes


【解决方案1】:

在大多数情况下,代码似乎仅从问题的角度起作用,printf 必须正确格式化。

printf("%i", length);

【讨论】:

    【解决方案2】:
    1. 需要类型转换 malloc
    2. 在函数参数长度中将 **head 更改为 *head
    3. 使用正确的 printf 语句。

    这个问题仅限于打印链接列表的长度。请在下面找到代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    struct node
    {
        int data;
        struct node *next;
    };
    
    struct node* BuildOneTwoThree();
    int Length(struct node* head);
    int main()
    {
        printf("Hello world!\n");
    
        struct node* mylist = BuildOneTwoThree();
        int length = Length(mylist);
    
        printf("data =%d\n",mylist->data);
        printf("length = %d",length);
        return 0;
    }
    
    
    // Return the number of nodes in a list (while-loop version)
    int Length(struct node* head) {
       int count = 0;
       struct node* current = head;
       while (current != NULL) {
          count++;
          current = current->next;
       }
       return(count);
    }
    
    /*
     Build the list {1, 2, 3} in the heap and store
     its head pointer in a local stack variable.
     Returns the head pointer to the caller.
    */
    struct node* BuildOneTwoThree() {
       struct node* head = NULL;
       struct node* second = NULL;
       struct node* third = NULL;
    
       head = (struct node *)malloc(sizeof(struct node)); // allocate 3 nodes in the heap
       second = (struct node *)malloc(sizeof(struct node));
       third = (struct node *)malloc(sizeof(struct node));
    
       head->data = 1; // setup first node
       head->next = second; // note: pointer assignment rule
       second->data = 2; // setup second node
       second->next = third;
       third->data = 3; // setup third link
       third->next = NULL;
       // At this point, the linked list referenced by "head"
       // matches the list in the drawing.
       return head;
    }
    

    【讨论】:

    • C 中不应使用 malloc 进行类型转换(在 C++ 中需要它,如果您出于某些特殊、明确的原因需要从 C++ 使用 malloc)。
    猜你喜欢
    • 2021-10-22
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多