在C中排序的链表

时间:2014-03-28 12:09:46

标签: c linked-list

在一些论坛和教程之后,我为已排序的链表编写了一个代码。代码导致核心转储。我相信错误发生在第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();

}

5 个答案:

答案 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的声明,valchar,而不是char *。编译器也应该抱怨这一点。

  • main()中,datachar *,您将指针的地址传递给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;
}