繁体   English   中英

在C中排序的链表

[英]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()datachar * ,并且您将指针的地址传递给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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM