[英]code not printing linked list C
我正在編寫C代碼來實現鏈接列表,但是在打印列表內容時僅打印最后一個節點的值,我已經調試了很長時間了,請幫忙。
#include <stdio.h>
#include <malloc.h>
struct list {
char *name;
char *type;
int occurance;
struct list *prev;
struct list *link;
};
struct list *start=NULL,*ptr,*newnode;
void main() {
int choice = 0;
char name1[10], type1[10];
int occ;
do {
printf("Enter name:");
scanf("%s", name1);
printf("Enter type:");
scanf("%s", type1);
printf("Enter occurance:");
scanf("%d", &occ);
newnode = (struct list *)malloc(sizeof(struct list));
newnode->link = NULL;
newnode->prev = NULL;
newnode->name = name1;
newnode->type = type1;
newnode->occurance = occ;
if(newnode == NULL) {
printf("Memory could not be allocated!");
// exit(0);
}
if(start == NULL) {
start = newnode;
ptr = start;
printf("start is: %s", start->name);
}
else if(start->link == NULL) {
start->link = newnode;
newnode->prev = start;
ptr = newnode;
}
else {
ptr->link = newnode;
newnode->prev = ptr;
ptr = ptr->link;
}
printf("Enter 1 to continue: ");
scanf("%d", &choice);
} while(choice == 1);
// display
ptr = start;
while(ptr != NULL) {
printf("%s ", ptr->name);
printf("%s ", ptr->type);
printf("%d \n", ptr->occurance);
ptr = ptr->link;
}
}
我也嘗試過使start和newnode
局部變量,但是它不起作用。
您不能使用equal運算符來分配char *
。 相反,您必須使用功能strcpy
。
不要這樣做:
newnode->name=name1;
newnode->type=type1;
但是這樣做:
strcpy(newnode->name, name1);
strcpy(newnode->type, type1);
當前,您的整個char*
都指向同一內存塊。
編輯:由於使用的是指針,因此必須在將值從一個指針復制到另一個指針之前分配內存(否則您將遇到段錯誤)。 因此,您還需要使用malloc
分配節點的名稱並鍵入malloc
:
//allocate memory of node's name attribute with the same amount as name1 (+1 for null terminating character)
newnode->name = malloc(sizeof(char) * (strlen(name1)+1));
newnode->type= malloc(sizeof(char) * (strlen(type1)+1));
您的代碼有幾處需要改進的地方,所以讓我們一一介紹。 首先,您看到的行為是因為鏈接列表中所有節點的結構成員name
和type
都指向相同的內存位置,即分別指向name1
和type1
。
struct list {
char *name;
char *type;
// other members
};
這里, name
是指向字符的指針, type
。 在main
的do while
循環中,您在每次迭代中分別將每個節點的名稱和類型讀入數組name1
和type1
中。 因此, name1
和type1
的先前值將被覆蓋並因此丟失。 現在,您要為每個新創建的節點的相應成員分配name1
和type1
。
// after allocating memory for a new node
newnode->name = name1; // name1 evaluates to a pointer to name1[0]
newnode->type = type1; // type1 evaluates to a pointer to type1[0]
因此,所有節點的name
成員都指向僅保留最近讀取的字符串的name1
,並且類似地,所有節點的type
成員指向也具有最近讀取的字符串的type1
。
既然我們已經討論了您的程序的行為,那么解決方案是什么? 您可以防止每個節點的名稱和類型被輸入的下一個值覆蓋。 為此,可以在每次為新節點讀取它們時為它們分配內存。
newnode->name = strdup(name1); // make a copy of name1 before it's overwritten
newnode->type = strdup(type1); // make a copy of type1 before it's overwritten
strdup
分配足夠的內存來復制傳遞給它的字符串。 它本質上與malloc
和strcpy
做相同的事情。 在此處了解更多信息。
現在讓我們從程序的頂部開始討論其他事情。
malloc.h
已過時,不是標准的。 請改用stdlib.h
。 這里更多。 main
函數設置了兩個簽名: int main(void);
另一個是int main(int argc, char *argv[]);
這里更多。 scanf
讀取字符串時,應防止緩沖區溢出。 如果用戶輸入的名稱和類型超過9個字符,將導致不確定的行為,甚至崩潰。 您應將scanf("%s", name1)
替換為scanf("%9s", name1)
。 格式字符串中的9
表示scanf
將最多讀取9個非空白字符。 終止的空字節保留一個字符空間,它會自動添加。 malloc
的返回值是否為NULL
。 這樣,如果malloc
未能分配內存,您的程序將很容易崩潰。 do while loop
,您do while loop
else if
塊。 除非在循環的第一個迭代start->previous = start
這不是您想要的),否則它將永遠不會輸入。 start->previous
應該始終為NULL
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.