簡體   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