在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 createdn");
}
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 listn");
}
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 %sn", &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);时,您正在破坏内存。此外,你想动态分配/释放这个内存不像char data[128],因为你希望每个节点有不同的数据。

这段代码有很多问题。它编译时没有警告吗?它能编译吗?

  • 在main()中,您在使用data之前没有初始化它。

  • create()和insert()都说它们返回struct node*,但不返回任何东西。

  • insert()将char *data作为参数,但是您在该函数中指定了tmpnode->val = data。根据你们对struct node的申报,valchar,而不是char *

  • main()中,datachar *,你将指针的地址传递给fscanf()。并且您没有为data分配任何内存,也没有将其初始化为任何非随机的东西,因此您将伪造指针的地址传递给fscanf()。

还有很多,但这是一个好的开始。如果您在编译器中禁用了警告,请再次启用它们——它们会告诉您一些重要的事情。如果你收到警告却忽略了它们,不要再忽略它们了——它们在告诉你一些重要的事情。

我几乎从头开始重新编写代码,我相信可能还有很多事情需要修复,但它确实对输入进行了排序。唯一困扰我的是,Valgrind抛出大量的错误为我的free - memory函数

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;
}

相关内容

  • 没有找到相关文章

最新更新