C链接列表 - 链接下一个链接列表节点

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C链接列表 - 链接下一个链接列表节点相关的知识,希望对你有一定的参考价值。

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

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()不返回NULL,如果确实则返回通知用户,否则用传递的数据填充临时ListNode

3)如果传递给函数的ListNode为NULL,只需将临时ListNode分配给传递的NULL ListNode并返回列表

4)如果传递给函数的ListNode不为NULL,并且传递的ListNode下一个值为NULL,则将临时ListNode分配给ListNode下一个值并返回列表

5)如果传递给函数的ListNode不为NULL,并且传递的ListNode下一个值不为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中。

任何帮助是极大的赞赏...

编辑

所以我的addtoList()函数现在在molbdnilo和Diego的推荐之后如下;

// 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()函数,它只返回一个字符串的副本,如下所示;

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++ != '\0')
    { 
        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 '\0' character at the end of the backup string.
        bkup_copy[orig_str_size] = '\0';

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

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

    return bkup_copy;

}

它现在按预期工作...如果有人能看到该代码的任何问题,请让我知道所以我现在可以解决它...

答案

问题是你不能取消引用NULL,你已经确定HeadNULL

您需要提前停止遍历,以便将新节点链接到列表中的最后一个节点。

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

以上是关于C链接列表 - 链接下一个链接列表节点的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 使用任意指针指向链接列表中的下一个更高值节点

单链接列表删除

Javascript中链接列表和节点的问题

从链接列表中删除节点无法正常工作

c_cpp 删除链接列表的备用节点

c_cpp 链接列表|设置3(删除节点)