【问题标题】:C Linked List - Linking next Linked List NodeC Linked List - 链接下一个链表节点
【发布时间】:2015-08-16 09:26:36
【问题描述】:

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

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 next value为NULL,则将临时ListNode赋给ListNode next value并返回列表

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 中。

非常感谢任何帮助...

编辑

所以我的 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;

}

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

【问题讨论】:

  • 另外,永远不要转换malloc返回的指针。
  • temp->data = data:这里需要复制数据;否则,所有节点都将指向同一个缓冲区
  • 它被标记为C&C++,因为有些程序员用C和C++编程,更多的是引起有能力的人的注意...
  • 如果你想引起懂c的人的注意,即使他们也懂c++,你也可以用c标签引起他们的注意。如果您需要帮助形成 c++ 程序员,一个明智的解决方案是将您的所有代码替换为 std::list
  • @xxwatcherxx 我很高兴能为您服务 :)

标签: c list pointers data-structures linked-list


【解决方案1】:

问题是你不能取消引用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;

【讨论】:

    猜你喜欢
    • 2018-01-21
    • 1970-01-01
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    相关资源
    最近更新 更多