[英]storing an array of nodes in linked list
我在链接列表中存储节点数组时遇到问题,每个节点都包含一个固定大小的值数组。 我的程序可以编译而不会出错,但是没有输出,我也不知道为什么。 这是我的Node和list的struct函数:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 20
typedef struct NODE Node;
struct NODE
{
char *bucket[SIZE];
int count;
Node *next;
};
Node *new_node()
{
Node *curr=malloc(sizeof( Node ));
curr->count=0;
curr->next=NULL;
return curr;
}
void add_node(Node *node,char *x)
{
node->bucket[node->count] = (char *)malloc( strlen( x ) + 1 );
strcpy(node->bucket[node->count],x);
node->count++;
}
typedef struct LIST List;
struct LIST
{
Node *top;
};
List *construct()
{
List *list;
list = malloc( sizeof( List ) );
list->top = NULL;
return list;
}
void insert( List *list, char *new_string )
{
Node *newNode = new_node();
Node *curr;
curr = list->top;
if ( NULL == curr)
{
curr=newNode;
}
add_node(newNode,new_string);
}
void print( List *list )
{
Node *curr = list->top;
while ( NULL != curr )
{
for(int i=0;i<curr->count;i++)
{
printf( "%s\n", curr->bucket[i]);
}
curr = curr->next;
}
}
这是我的测试功能:
int main(int argc, char const *argv[])
{
List *list=construct();
char *ch="a";
insert(list,ch);
insert(list,ch);
insert(list,ch);
insert(list,ch);
insert(list,ch);
print(list);
return 0;
}
有什么想法为什么这表现不如预期吗?
主要问题是您的insert()
函数。
void insert(List *list, char *new_string)
{
Node *newNode = new_node();
Node *curr;
curr = list->top;
if (NULL == curr) {
/* OK. We set curr to newNode, but what happens to curr? */
curr = newNode;
}
/* String is added to newNode, but what happens to newNode? */
add_node(newNode, new_string);
}
如果您改为说(您可能打算这样做):
if (list->top == NULL) {
list->top = newNode;
}
您将保留第一个 newNode
,但保留其余的。
当涉及到add_node()
,它没有直接的问题。 最大的问题是您不检查node->count
是否为20。其次,它的名称很不好 。 给函数命名时要小心,否则代码将变得很难阅读和维护。
add_node
不添加一个节点。 名称应反映其作用。
例如,您可以说:
insert
应该被命名为add_node
,而add_node
应该被命名为add_string
, push_string
, bucket_fill
等。 至少那会更好。
强制转换malloc也是多余的:
node->bucket[node->count] = (char*)malloc(strlen(str) + 1);
更好(IMHO):
node->bucket[node->count] = malloc(strlen(str) + 1);
有多种添加新节点的方法。 一种方法是循环直到最后并添加:
while (node->next != NULL) {
node = node->next;
}
node->next = new_node();
bucket_fill(node->next, str);
如果您有单独的列表结构,则可以跟踪头和尾:
struct list {
struct node *head;
struct node *tail;
};
然后类似:
void node_add(struct list *list, char *str)
{
struct node *new_node = node_create();
bucket_fill(new_node, str);
if (list->head != NULL) {
list->tail->next = new_node;
list->tail = new_node;
} else {
list->head = new_node;
list->tail = new_node;
}
}
等等等等。
查看每个步骤,并尝试跟踪节点。
通常,一个人不会有一个struct list
和一个struct node
,但是对这两者都使用node
。 本质上,列表是节点链中的第一个节点。
在编码链表(通常是C)时,真正有用的一件事是使用Valgrind(至少在Linux等系统上)。 为了free_list()
更有用,您首先需要添加free_list()
函数以释放内存。
使用malloc
编写函数时,请务必始终编写一个free
函数。
然后使用以下命令运行程序:
$ valgrind ./my_program
如果将gcc
compile与-ggdb
一起使用,则可从Valgrind的输出中获取行号。
那么对您有用的两种情况是确保退出时释放所有内存。 这样可以确保您不会错过任何代码。 其次,当您访问未初始化的变量等时,您将收到警告。
首先,有两件事要看:
1.)无泄漏。 “在出口使用”应为0。
==13476== HEAP SUMMARY:
==13476== in use at exit: 0 bytes in 0 blocks
==13476== total heap usage: 43 allocs, 43 frees, 424 bytes allocated
==13476==
==13476== All heap blocks were freed -- no leaks are possible
2.)使用未初始化的值:
==12972== Conditional jump or move depends on uninitialised value(s)
==12972== by 0x8048838: insert (foo.c:120)
==12972== by 0x804890E: main (foo.c:151)
|
|
+--- Shows file and line-number.
要么:
==12820== Use of uninitialised value of size 4
...
等等。
典型的免费功能可能是这样的:
void free_bucket(struct node *node)
{
int i;
for (i = 0; i < node->count; ++i) {
free(node->bucket[i]);
}
}
void free_list(struct node *head)
{
struct node *tmp_node;
while (head != NULL) {
free_bucket(head);
tmp_node = head;
head = head->next;
free(tmp_node);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.