[英]C Linked list pointer problems (infinite loop)
編輯:添加了新代碼,當前問題是當我插入一個節點時,它工作正常,但是如果我插入多個節點,則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;
}
}
您的代碼有幾個問題。
首先,您分配了過多的內存。 臨時局部變量只是指向現有內存的指針。 您要分配內存的唯一位置是create_book
,您可以在其中創建數據。 您必須通過稍后刪除節點來free
該內存。 (我認為您可能會對指針所扮演的不同角色感到困惑:有時它們只是標識新分配的內存,更多時候它們被用於訪問和遍歷已經存在的內存。)
接下來, head
本身並不是一個節點,它只是指向第一個節點的指針。 如果沒有節點,則此指針為NULL
。 在程序開始時就是這樣,這意味着您必須對其進行初始化:
node* head = NULL;
但是,如果所有書籍都已從清單中刪除,也是如此。 顯然,如果添加第一個節點或刪除第一個節點,則head
改變。 您的insert_node
應該注意這些更改。 一種方法是將head作為指針傳遞給節點指針。
(在C語言中,作為參數傳遞的所有內容都是本地副本。更改is將使調用函數中的原始值保持不變。但是,如果傳遞指針,則在調用函數和被調用函數中指向的東西都是相同的。您可以通過poiner進行更改。)
此外,無論是head
需要改變應該是關注insert_node
的不是調用( 客戶端 )的代碼, main
。 如果跳過所有錯誤的malloc,則插入會容易得多:
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
。 該緩沖區用於循環輸入,在打印書籍時,該緩沖區包含第三本書的值。 這意味着列表中的所有書籍將具有相同的名稱和作者。
解決此問題的一種方法是將指向緩沖區的內容復制到該結構中,該結構當然必須為其緩沖區提供內存,如上所示。 您的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
,將其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
fo short作為到達列表末尾的便捷標准。 ( print_node
函數不需要將head
作為指針傳遞給node指針,因為它從不更改列表,而只是檢查其數據。)
仍然有一些問題需要解決,例如在使用后刪除節點(或while列表)以及如何處理分配失敗的問題,但是通過這些更改,您的代碼至少應該編譯並運行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.