[英]sorted linked list in C
在一些論壇和教程之后,我編寫了用於排序鏈表的代碼。 該代碼導致核心轉儲。 我相信錯誤是在第50行之后,我嘗試在最后插入節點。 您能幫我解決這個錯誤嗎? 我不確定自己在做什么錯。 謝謝。
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
struct node
{
char val;
struct node* next;
};
struct node *start = (struct node*) NULL;
// definition of creating only first node
struct node* create(char* data)
{
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
if (start == NULL)
{
temp->val = data;
temp->next = NULL;
start = temp;
}
printf("List created\n");
}
struct node* insert(char* data)
{
int i, pos;
struct node* tempnode, *ptr;
ptr = start;
while(ptr != NULL)
{
if (data <= ptr->val)
{
printf("!!!Inserting before!!!\n");
tempnode = (struct node*)malloc(sizeof(struct node));
tempnode->val = ptr->val;
tempnode->next=ptr->next;
ptr->val = data;
ptr->next=tempnode;
break;
}
else if (data > ptr->val)
{
printf("!!!Going next!!!\n");
ptr = ptr->next;
}
if (ptr == NULL) //insert behind the node
{
tempnode = (struct node*)malloc(sizeof(struct node));
tempnode->val = data;
tempnode->next = NULL;
ptr->next = tempnode;
printf("!!!Placed at the end!!!\n");
break;
}
}
}
void display()
{
struct node* ptr; // ptr is pointer
ptr = start;
while (ptr != NULL)
{
printf("%s->", ptr->val);
ptr = ptr->next;
}
printf("End of list\n");
}
int main()
{
char* data;
int i = 0;
create(0);
FILE* file = fopen("words.txt", "r");
while (i < 10)
{
fscanf(file, "%s", &data);
printf ("data is %s\n", &data);
insert(data);
i++;
}
display();
}
在這里,在insert
函數的底部,您已保證ptr
為NULL,但您仍然要進行ptr->next = ...
這等效於(*ptr).next = ...
,它取消引用NULL指針!
if (ptr == NULL) //insert behind the node
{
tempnode = (struct node*)malloc(sizeof(struct node));
tempnode->val = data;
tempnode->next = NULL;
ptr->next = tempnode;
printf("!!!Placed at the end!!!\n");
break;
}
局部變量永遠不會被初始化,它們的值是不確定的(並且似乎是隨機的)。 使用未初始化的局部變量會導致未定義的行為 。
現在看一下main
函數中的data
變量:它是未初始化的,因此在您將其實際指向某個位置之前無法使用。 由於您不這樣做,所以您有未定義的行為。 你還在錯誤地使用它fscanf
調用,如您通過指針的地址fscanf
。 盡管參數應該是指針,但data
已經是指針。 您只需要為其分配內存。 這是通過使它成為數組而不是指針來完成的最簡單的操作:
char data[128];
還有其他一些問題,例如您使用<=
類的比較運算符來比較字符串。 這只會比較指針。 使用strcmp
比較字符串。 另一個問題是,即使修復了上述問題,它也無法按預期工作,這是因為對所有節點都使用了相同的字符串指針。 添加節點時,您需要復制字符串。 這可以通過strdup
函數完成:
ptr->val = strdup(data);
當然,由於此操作使用malloc
為字符串分配內存,因此您必須手動free
此內存。
我的第一個觀察結果是您尚未將內存分配給main中的char* data
。 這樣,您在執行fscanf(file, "%s", data);
時會損壞內存fscanf(file, "%s", data);
。 另外,由於您希望每個節點具有不同的數據,因此您不希望像char data[128]
那樣動態分配/取消分配該內存。
此代碼有很多問題。 它會在沒有警告的情況下編譯嗎? 它可以編譯嗎?
在main()中,您尚未在使用之前初始化data
。 大多數編譯器會警告您。
create()和insert()都說它們返回struct node*
但不返回任何東西。 編譯器應該對此抱怨。
insert()將char *data
作為參數,但是您要在該函數中分配tmpnode->val = data
。 根據您對struct node
的聲明, val
是一個char
,而不是char *
。 編譯器也應該對此抱怨。
在main()
, data
是char *
,並且您將指針的地址傳遞給fscanf()
。 而且您沒有為data
分配任何內存,也沒有將其初始化為任何非隨機的數據,因此您要將偽指針的地址傳遞給fscanf()。
還有很多,但這是一個好的開始。 如果您在編譯器中禁用了警告,則將其啟用agian-它們會告訴您一些重要的信息。 如果您收到警告並忽略它們,請不要忽略它們-它們在告訴您重要的事情。
我幾乎從頭開始重新編寫了代碼,並且我敢肯定可能還有很多事情要修復,但是它確實對輸入進行了排序。 唯一令我困擾的是Valgrind為我的Freememory函數拋出了很多錯誤
HEAP SUMMARY:
==8731== in use at exit: 0 bytes in 0 blocks
==8731== total heap usage: 9 allocs, 32 frees, 1,016 bytes allocated
==8731==
==8731== All heap blocks were freed -- no leaks are possible
==8731==
==8731== For counts of detected and suppressed errors, rerun with: -v
==8731== ERROR SUMMARY: 38 errors from 6 contexts (suppressed: 2 from 2)
無論如何,我的解決方案在這里:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// maximum length for a word
#define LENGTH 45
// default dictionary
#define DICTIONARY "words.txt"
typedef struct node
{
char word[LENGTH + 1];
struct node* next;
}
Word;
Word *head = NULL; //start
Word *cur = NULL; //cursor
Word *cur2 = NULL; //cursor
/****************************************/
/* PROTOTYPES */
/****************************************/
Word* create(char *node);
void display();
void freememory();
/****************************************/
/* FUNCTIONS */
/****************************************/
Word* create(char *node)
{
Word *new_node = NULL;
new_node = (Word*)malloc(sizeof(Word));
strncpy(new_node->word, node, LENGTH);
if(head==NULL)
{
head=new_node;
new_node->next=NULL;
}
else
{
cur = head;
cur2 = cur->next;
while (cur != NULL)
{
if (strcmp(new_node->word, cur->word) > 0 )
{
if (cur->next == NULL)
{
new_node->next = NULL;
cur->next = new_node;
break;
}
else if (strcmp(new_node->word, cur->word) > 0 && strcmp(new_node->word, cur2->word) <= 0)
{
new_node->next = cur->next;
cur->next = new_node;
break;
}
}
else if (strcmp(new_node->word, cur->word) <= 0 )
{
new_node->next = head;
head = new_node;
break;
}
cur = cur->next;
cur2 = cur2->next;
}
}
return head;
}
// output the list
void display()
{
//Word *Wordlist;
cur = head;
while (cur != NULL)
{
printf("%s->", cur->word);
cur = cur->next;
}
printf("End of the list!\n");
}
// free allocated memory
void freememory()
{
Word *temp = NULL;
Word *temp2 = NULL;
cur = head;
cur2 = head;
while(cur != NULL)
{
temp = cur;
cur = cur->next;
free(cur);
free(temp);
}
while(cur2 != NULL)
{
temp2 = cur2;
cur2 = cur2->next;
free(cur2);
free(temp2);
}
free(head);
}
/****************************************/
/* M A I N */
/****************************************/
int main()
{
system("clear");
char data[LENGTH];
FILE* file = fopen(DICTIONARY, "r");
// check successful opening of the file
if(file == NULL) {
perror("Error opening file");
return -1;
}
//read data (words) from file
while(fscanf (file, "%s", data) == 1)
{
create(data);
}
display();
freememory();
fclose(file);
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.