【问题标题】:Explain generic linked list in C解释 C 中的通用链表
【发布时间】:2017-05-08 17:50:25
【问题描述】:

请解释一下推送功能。我不明白为什么要使用循环。对于 char 和 int (new_node->data=new_data) 工作正常。但对于 string ,它没有。对于 string ,会产生错误。如果在 push() 方法中为 new_data 打印 char(%c) 则只打印第一个字符,而如果为 new_node->data 打印 char(%c) 则打印最后一个字符。

// C program for generic linked list
#include<stdio.h>
#include<stdlib.h>

/* A linked list node */
struct node
{
    // Any data type can be stored in this node
    void  *data;

    struct node *next;
};

/* Function to add a node at the beginning of Linked List.
   This function expects a pointer to the data to be added
   and size of the data type */
void push(struct node** head_ref, void *new_data, size_t data_size)
{
    // Allocate memory for node
    struct node* new_node = (struct node*)malloc(sizeof(struct node));

    new_node->data  = malloc(data_size);
    new_node->next = (*head_ref);

    // Copy contents of new_data to newly allocated memory.
    // Assumption: char takes 1 byte.
    int i;
    //Why loop is used for copying data from new_data to new_node data.
    for (i=0; i<data_size; i++)
        *(char *)(new_node->data + i) = *(char *)(new_data + i);

    // Change head pointer as new node is added at the beginning
    (*head_ref)    = new_node;
}

/* Function to print nodes in a given linked list. fpitr is used
   to access the function to be used for printing current node data.
   Note that different data types need different specifier in printf() */
void printList(struct node *node, void (*fptr)(void *))
{
    while (node != NULL)
    {
        (*fptr)(node->data);
        node = node->next;
    }
}

// Function to print an integer
void printInt(void *n)
{
   printf(" %d", *(int *)n);
}

// Function to print a float
void printFloat(void *f)
{
   printf(" %f", *(float *)f);
}

/* Driver program to test above function */
int main()
{
    struct node *start = NULL;

    // Create and print an int linked list
    unsigned int_size = sizeof(int);
    int arr[] = {10, 20, 30, 40, 50}, i;
    for (i=4; i>=0; i--)
       push(&start, &arr[i], int_size);
    printf("Created integer linked list is \n");
    printList(start, printInt);

    // Create and print a float linked list
    unsigned float_size = sizeof(float);
    start = NULL;
    float arr2[] = {10.1, 20.2, 30.3, 40.4, 50.5};
    for (i=4; i>=0; i--)
       push(&start, &arr2[i], float_size);
    printf("\n\nCreated float linked list is \n");
    printList(start, printFloat);

    return 0;
}

【问题讨论】:

  • 循环只是复制数据。它的作用类似于memcpy(new_node-&gt;data, new_data, data_size);,这是因为您的链表旨在保存任何数据类型。在 C 中,这意味着原始字节和sizeofs。
  • / Any data type can be stored in this node void *data;。嗯long double 可能不适合。指向函数的指针也可能不适合。不过对于对象指针来说已经足够了。
  • 指向void*的指针算术运算也无效。 (它是 GCC 扩展)
  • 我想你想要像*( ((char *)new_node-&gt;data) + i) 这样的东西。 memcpy() 会更好。

标签: c data-structures


【解决方案1】:

是的,我们也可以使用new_node-&gt;data=new_data 来代替这个循环

for (i=0; i<data_size; i++)
            *(char *)(new_node->data + i) = *(char *)(new_data + i);

但它们之间是有区别的。当我们简单地使用new_node-&gt;data=new_data 时,我们是浅拷贝。因此,两个指针指向同一个位置,即如果您更改 arr[] 的值,那么结构中的值会自动更改。 当您使用循环时,您将进行深度复制,即如果您更改 arr[] 的值,那么结构的值将不会改变。 运行下面的代码来了解区别。

// C program for showing shallow copy in generic linked list
#include<stdio.h>
#include<stdlib.h>

/* A linked list node */
struct Node
{
    // Any data type can be stored in this node
    void  *data;

    struct Node *next;
};

/* Function to add a node at the beginning of Linked List.
   This function expects a pointer to the data to be added
   and size of the data type */
void push(struct Node** head_ref, void *new_data, size_t data_size)
{
    // Allocate memory for node
    struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));

    new_node->data  = malloc(data_size);
    new_node->next = (*head_ref);

    // Copy contents of new_data to newly allocated memory.
    // Assumption: char takes 1 byte.
    int i;
    // no loop just normal assignment of new_data
        new_node->data=new_data;
    printf("\n");

    // Change head pointer as new node is added at the beginning
    (*head_ref)    = new_node;
}

/* Function to print nodes in a given linked list. fpitr is used
   to access the function to be used for printing current node data.
   Note that different data types need different specifier in printf() */
void printList(struct Node *node, void (*fptr)(void *))
{
    while (node != NULL)
    {
        (*fptr)(node->data);
        node = node->next;
    }
}

// Function to print an integer
void printInt(void *n)
{
    printf(" %d", *(int *)n);
}

// Function to print a float
void printFloat(void *f)
{
    printf(" %f", *(float *)f);
}

/* Driver program to test above function */
int main()
{
    struct Node *start = NULL;

    // Create and print an int linked list
    unsigned int_size = sizeof(int);
    int arr[] = {1,2,3,4,5}, i;
    for (i=4; i>=0; i--)
        push(&start, &arr[i], int_size);
    printf("Created integer linked list is \n");
    printList(start, printInt);
    printf("\n");
    // changing the values in arr[]
    arr[1]=45;
    arr[3]=1000;
    //printing the struct
    printf("printing the struct after changing the values in the array \n");
    printList(start, printInt);
    /*
    // Create and print a float linked list
    unsigned float_size = sizeof(float);
    start = NULL;
    float arr2[] = {10.1, 20.2, 30.3, 40.4, 50.5};
    for (i=4; i>=0; i--)
        push(&start, &arr2[i], float_size);
    printf("\n\nCreated float linked list is \n");
    printList(start, printFloat);*/

    return 0;

    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 2012-06-25
    • 1970-01-01
    相关资源
    最近更新 更多