在一些论坛和教程之后,我为已排序的链表编写了一个代码。代码导致核心转储。我相信错误发生在第50行之后,我试图在最后插入节点。你能帮我解决一下这个bug吗?我不确定我做错了什么。感谢。
#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();
}
答案 0 :(得分:2)
此处,在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;
}
答案 1 :(得分:2)
局部变量永远不会被初始化,它们的值是不确定的(并且似乎是随机的)。使用未初始化的局部变量会导致未定义的行为。
现在查看data
函数中的main
变量:它未初始化,因此无法使用,直到您确实将其指向某处。既然你不这样做,你就有未定义的行为。当您将指针的地址传递给fscanf
时,您也会在fscanf
调用中错误地使用它。虽然参数应该是指针,但data
已经是指针。你只需要为它分配内存。这是最简单的方法,使它成为一个数组而不是一个指针:
char data[128];
还有一些其他问题,例如您使用比较运算符(如<=
)来比较字符串。这只会比较指针。使用strcmp
比较字符串。另一个问题是,即使修复了上述内容,它也无法正常工作,这是因为您对所有节点使用相同的字符串指针。添加节点时需要复制字符串。这可以使用strdup
函数完成:
ptr->val = strdup(data);
当然,由于这会使用malloc
为字符串分配内存,因此您必须手动free
此内存。
答案 2 :(得分:0)
我的第一个观察是你没有在main中为char* data
分配内存。
这样,在执行fscanf(file, "%s", data);
时就会破坏内存。此外,您希望动态分配/取消分配此内存,而不是char data[128]
,因为您希望每个节点都有不同的数据。
答案 3 :(得分:0)
此代码存在许多问题。没有警告就编译吗?是否可以编译?
在main()中,您在使用之前尚未初始化data
。大多数编译器会警告你。
create()和insert()都说它们返回struct node*
但不返回任何内容。编译器应该抱怨这一点。
insert()将char *data
作为参数,但您在该函数中指定tmpnode->val = data
。根据您对struct node
的声明,val
是char
,而不是char *
。编译器也应该抱怨这一点。
在main()
中,data
是char *
,您将指针的地址传递给fscanf()
。并且你没有为data
分配任何内存,也没有将它初始化为非随机的内容,因此你将伪指针的地址传递给fscanf()。
还有更多,但这是一个好的开始。如果您在编译器中禁用了警告,请启用它们agian - 它们会告诉您重要的事情。如果您收到警告并忽略它们,请不要再忽略它们 - 它们会告诉您重要的事情。
答案 4 :(得分:0)
我几乎从头开始重新编写代码,我确信可能还有很多东西要修复,但它会对输入进行排序。唯一困扰我的是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;
}