C Linked List - 链接下一个链表节点

C Linked List - Linking next Linked List Node

我有一个接受多个命令行参数的应用程序,在这些参数中,它接受一个目标主机文件,将对其执行某些操作。

173.194.40.225
157.55.152.112
200.49.185.230
195.95.178.226
98.158.27.203

每一行是目标的IP地址,我使用以下函数遍历文件;

// Open file read line by line to Linked List
ListNode* file(char *file, char *option) 
{

    FILE *ptr_file;
    char buffer[1000];
    char *destination;
    ListNode *linelist;

    // Create an empty line list
    linelist = NULL; 

    // Open a file
    if(strcmp(option, "r") == 0)
    {
        ptr_file = fopen(file, option);

        if(!ptr_file)
        {
            printf("Can\'t open file\n\n");
            exit(0);
        }
    }
    else
    {
        printf("File operation not implemented\n\n");
        exit(0);
    }

    // Traverse through the file 
    while (fgets(buffer, LINE_MAX, ptr_file) != NULL)
    {
        printf("Line: %s\n", buffer);

        // Add line to Linked List
        linelist = addtoList(linelist, buffer);

        printf("---------------------------------------\n\n");
    }

    printList(linelist);

    // Close the file
    fclose(ptr_file);

    // Return a pointer to linelist
    return linelist;
}

该函数应该传回一个指向目标 IP 地址链接列表的指针,该链接列表可在单独的套接字函数中使用。链表设计如下;

// Define node structure
struct listnode 
{
    char *data;
    struct listnode *next;
};

// Define node as a type
typedef struct listnode ListNode;

// Add to List
ListNode* addtoList( ListNode *List, char *data );

在 file() 函数使用 while 循环和 fgets() 遍历传递的文件以将每一行加载到缓冲区之后,缓冲区被传递给 addtoList() 函数,该函数接受两个变量,一个指向链表和一个指向 char 的指针,实际上它只是传递文件的每一行。该函数旨在添加到传递列表的末尾。

函数的工作原理如下;

1) 创建一个类型为 ListNode 的临时指针并使用 malloc()

分配内存

2) 检查 malloc() 是否 return NULL,如果是则通知用户,否则用传递的数据填充临时 ListNode

3)如果传递给函数的ListNode为NULL,只需将临时ListNode赋值给传入的NULL ListNode和return列表

4)如果传递给函数的ListNode不为NULL,并且传入的ListNode next值为NULL,将临时ListNode赋值给ListNode next value和returnlist

5) 如果传递给函数的ListNode不为NULL,并且传入的ListNode next值不为NULL,则创建指向链表开头的指针的副本。使用 while 循环遍历列表,直到我们到达最后一个为 NULL 的 ListNode。将临时 ListNode 分配给 NULL ListNode

函数如下;

// Add to List
ListNode* addtoList(ListNode *List, char *data)
{

    printf("Adding: %s\n", data);

    // Create pointer to allocated memory the size of a ListNode
    ListNode* temp = (ListNode*)malloc( sizeof( ListNode ) );

    // Check malloc didn't return NULL
    if(temp == NULL) 
    {
        printf( "Can\'t allocate memory for temp, failed to allocate the requested block of memory, a null pointer is returned\n\n" ); 
        exit(0);
    }
    else
    {
        printf("Memory allocated for temp, filling allocated memory\n\n");

        // Fill the allocated memory where data is a pointer to data
        temp->data = data;
        temp->next = NULL;

        printf("Allocated memory for temp filled with data\n\n");

    }

    printf("temp->data = %s\n\n", temp->data);

    int size = countList(List);
    printf("List size: %i\n\n", size);

    if(List == NULL)
    {
        // If computer can't allocate memory let us know
        printf( "List is empty\n\n" ); 
        List = temp;
        printf( "List is now temp\n\n" ); 
        return List;
    }
    else
    if(List != NULL && List->next == NULL) 
    {
        printf("List isn\'t empty and List->next is NULL\n\n");

        List->next = temp;
        return List;
    }
    else
    if(List != NULL && List->next != NULL) 
    {
        printf("List isn\'t empty and List->next is not NULL\n\n");

        ListNode* Head = List;

        while(Head != NULL)
        {
            printf("List->next data: %s List->next pointer: %p\n\n", Head->data, Head->next);
            Head = Head->next;
        }

        if(Head == NULL)
        {

            printf("Head equals null\n");
            //problem here
            Head->next = temp;

        }

        return List;
    }

}

我的问题出在 if(Head == NULL) 条件语句中的 addtoList() 函数的最后,将临时 ListNode 分配给 Head->next;

if(Head == NULL)
{     
    printf("Head equals null\n");
    //problem here
    Head->next = temp;      
}

应用程序输出如下;

######################################

Line: 173.194.40.225

Adding: 173.194.40.225

Memory allocated for temp, filling allocated memory

Allocated memory for temp filled with data

temp->data = 173.194.40.225


List size: 1

List is empty

List is now temp

---------------------------------------

Line: 157.55.152.112

Adding: 157.55.152.112

Memory allocated for temp, filling allocated memory

Allocated memory for temp filled with data

temp->data = 157.55.152.112


List size: 2

List isn't empty and List->next is NULL

---------------------------------------

Line: 200.49.185.230

Adding: 200.49.185.230

Memory allocated for temp, filling allocated memory

Allocated memory for temp filled with data

temp->data = 200.49.185.230


List size: 3

List isn't empty and List->next is not NULL

List->next data: 200.49.185.230
 List->next pointer: 0x8592180

List->next data: 200.49.185.230
 List->next pointer: (nil)

Head equals null
Segmentation fault

我遇到的问题是将临时 ListNode 分配给 listnode 结构的 NULL ListNode。

非常感谢任何帮助...

编辑

根据 molbdnilo 和 Diego 的建议,我的 addtoList() 函数现在如下所示;

// Add to end of List
ListNode* addtoList(ListNode *List, char *data)
{

    char* data_ptr = data;    // Create a pointer to passed data
    char* bkup_copy = NULL;   // Create a null pointer for backing up passed data

    bkup_copy = copyString(data_ptr); // Create a backup of data

    // Create pointer to allocated memory the size of a ListNode
    ListNode* temp = (ListNode*)malloc( sizeof( ListNode ) );

    // Check malloc didn't return NULL
    if(temp == NULL) 
    {
        printf("Can\'t allocate memory for temp, failed to allocate the requested block of memory, a null pointer returned\n\n" ); 
        exit(0);
    }
    else
    {
        // Fill the allocated memory where data is a pointer to data
        temp->data = bkup_copy;
        temp->next = NULL;       
    }

    if(List == NULL)
    {
        List = temp;
        return List;
    }
    else
    if(List != NULL && List->next == NULL) 
    {
        List->next = temp;
        return List;
    }
    else
    if (List != NULL && List->next != NULL) 
    {

        // Create a copy of pointer to passed list
        ListNode* Head = List;

        // Traverse through the list until last item
        while(Head->next != NULL)
        {
            Head = Head->next;
        }

        // Assign temp to the last list item next
        Head->next = temp;

        return List;
    }
    else
    {
        printf("Unknown state of List\n\n");
        exit(0);
    }

}

使用新的 copyString() 函数,它只是 return 一个字符串的副本,如下所示;

char* copyString(char* data)
{

    char* data_ptr = data;    // Create a pointer to passed data
    int orig_str_size = 0;    // Create an int to hold passed data size
    char* bkup_copy = NULL;   // Create a null pointer to backup passed data
    int bkup_index = 0;       // Create a index variable for traversal of passed data
    int length;

    // Count the number of characters in data_ptr
    while (*data_ptr++ != '[=17=]')
    { 
        orig_str_size++; 
    }

    // Dynamically allocate space for a backup copy of data
    bkup_copy = (char*)malloc((orig_str_size+1) * sizeof(char));

    // Check malloc didn't return NULL
    if(bkup_copy == NULL) 
    {
        printf("Can\'t allocate memory for bkup_copy, failed to allocate the requested block of memory, a null pointer returned\n\n" ); 
        exit(0);
    }
    else // Copy data to separate allocated memory
    {
        // Place the '[=17=]' character at the end of the backup string.
        bkup_copy[orig_str_size] = '[=17=]';

        // Assign the pointer to data to the first pointer position in data
        data_ptr = &data[0]; 

        // The backup string is not the '[=17=]' character copy data to bkup_copy
        while (*data_ptr != '[=17=]'){ bkup_copy[bkup_index++] = *data_ptr++; }
    }

    return bkup_copy;

}

它现在按预期工作...如果有人发现该代码有任何问题,请告诉我,以便我现在可以修复它...

问题是您无法取消引用 NULL,并且您已经非常确定 Head NULL

你需要提前停止遍历,这样你就可以link新节点到链表的最后一个节点。

    // Find the last node - the node with NULL as its 'next'
    while (Head->next != NULL)
    {
        Head = Head->next;
    }
    // 'Head' is now the last node.
    // Replace the NULL at the end of the list with the new node.
    Head->next = temp;