[英]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.