编辑:新代码添加,当前问题是当我插入一个节点它工作正常,但如果我插入任何多个节点,insert_node方法永远不会完成,第一个语句打印,说“插入调用”然后它永远不会完成永远不会打印“插入完成”。
我唯一能想到的是while循环条件,但我不明白为什么这会是无限的。
此外,当我插入1个节点时,它打印正常,但它永远不会停止打印,再次是另一个无限循环。
关于错误原因的任何想法?
/*
* File: main.c
* Author: che16
*
* Created on 20 November 2013, 08:59
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "structure.h"
/*
*
*/
node* head = NULL;
int set_head = 0;
int main(int argc, char** argv) {
int no;
printf("enter amount of books \n");
scanf("%d", &no);
create_books(no);
print_list(head);
return (EXIT_SUCCESS);
}
node* create_books(int no_of_books) {
char title[50];
char author[30];
unsigned int number;
int i;
for (i = 0; i < no_of_books; i++) {
node* new_node;
new_node = (node *) malloc(sizeof (node));
printf("enter book title \n");
scanf("%s", title);
printf("enter author name \n");
scanf("%s", author);
printf("enter ISDN number \n");
scanf("%10u", &number);
strncpy(new_node->btitle, title, 40);
strncpy(new_node->name, author, 40);
new_node->isbn = number;
new_node->n = NULL;
if (!set_head) {
head = new_node;
insert_node(head, new_node);
set_head = 1;
continue;
}
insert_node(head, new_node);
}
}
void insert_node(node* head, node* insert) {
printf("insert called \n");
insert->n = NULL;
if (head == NULL) {
head = insert;
} else {
node* curr = head;
while (curr->n != NULL) {
curr = curr->n;
}
curr->n = insert;
}
printf("insert complete \n");
}
void delete_node(node* head, node * node) {
}
void print_list(node * head) {
while (head) {
printf("%s: \"%s\" (%u)\n", head->btitle, head->name, head->isbn);
head = head->n;
}
}
答案 0 :(得分:0)
您的代码存在一些问题。
首先,你分配了太多的内存。临时局部变量只是指向现有内存的指针。您想要分配内存的唯一位置是create_book
,您可以在其中创建数据。通过稍后删除节点,您必须free
该内存。 (我认为您可能会对指针所扮演的不同角色感到困惑:有时它们只是识别新分配的内存,更常见的是它们用于访问和遍历已有的内存。)
接下来,head
本身不是一个节点,它只是指向第一个节点的指针。如果没有节点,则此指针为NULL
。这在程序开始时就是如此,这意味着你必须初始化它:
node* head = NULL;
但是如果从列表中删除所有书籍也是如此。显然,如果添加第一个节点或删除第一个节点,head
会发生变化。您的insert_node
应该注意这些变化。一种方法是将头部作为指针传递给节点指针。
(在C中,作为参数传递的所有内容都是本地副本。更改将使调用函数中的原始值保持不变。但是如果传递指针,则指向的东西在调用和调用中都是相同的叫做函数。你可以通过poiner改变它。)
此外,head
是否需要更改应该是insert_node
的关注点,而不是main
中的调用(客户端)代码。如果你跳过所有错误的mallocs,插入就容易了:
void insert_node(node **head, node* insert)
{
insert->n = NULL;
if (*head == NULL) {
*head = insert;
} else {
node* curr = *head;
while (curr->n) curr = curr->n;
curr->n = insert;
}
}
您可以无条件地从main
调用此内容:
insert_node(&head, create_book(title, author, number));
请注意所有这些也会导致head_set
多余:如果head
已设置,则它具有合法指针值,否则为NULL
。
出现抱怨不兼容指针的编译器错误,因为该结构没有名称。在C中,结构类型由单词struct
定义,然后由其名称定义。有些人认为struct
关键字是不必要的,typedef
结构为单字类型。您可以在一个语句中执行此操作。你可以声明:
typedef struct node {
char btitle[40];
char name[40];
unsigned int isbn;
struct node* n;
} node;
或者你可以分开类型和结构:
typedef struct node node;
struct node {
char btitle[40];
char name[40];
unsigned int isbn;
struct node* n;
};
(typedef
可能会进入主源文件中的标题和结构。)
您会注意到我已将char *btitle
更改为char btitle[40]
。如果只存储指向标题的指针,则基本上存储指向title
中本地缓冲区main
的指针。此缓冲区用于循环中的输入,并且在打印书籍时,缓冲区包含第三本书的值。这意味着列表中的所有书籍都将具有相同的名称和作者。
解决此问题的一种方法是将指向缓冲区的内容复制到struct中,当然必须为其缓冲区提供内存,如上所示。您的create_book
变为:
node* create_book(char* t, char* auth, unsigned int num)
{
node* new_node;
new_node = malloc(sizeof (node));
strncpy(new_node->btitle, t, 40);
strncpy(new_node->name, auth, 40);
new_node->isbn = num;
new_node->n = NULL;
return new_node;
}
例程strncpy
从第二个缓冲区到第一个缓冲区最多复制40个字符。您应该为原型包含<string.h>
。另请注意,我将指向下一个节点的指针n
显式初始化为NULL
,正如我在main中使用head
所做的那样。下一节点指针始终是NULL
或指向有效节点的指针。
现在插入工作正常,打印列表很简单:
void print_list(node* head)
{
while (head) {
printf("%s: \"%s\" (%u)\n", head->btitle, head->name, head->isbn);
head = head->n;
}
}
查看代码如何仅使用节点本身中包含的数据,以及如何使用head == NULL
或head
短消息作为达到列表末尾的便捷标准。 (print_node
函数不要求将head
作为指向节点指针的指针,因为它永远不会更改列表,只检查其数据。)
还有一些问题需要解决,例如在使用后删除节点(或while列表)以及如何处理不成功的分配,但是通过这些更改,您的代码至少应该编译并运行。