【问题标题】:How to make a nested list in C using a single linked list struct format which contains a void pointer and a recursive pointer to the struct?如何使用包含 void 指针和指向结构的递归指针的单链表结构格式在 C 中创建嵌套列表?
【发布时间】:2021-04-20 01:42:56
【问题描述】:

任务是将现有列表按长度排序到另一个嵌套列表中。

["x", "yy", "zzz", "f", "gg"] ergeben 
 [["x", "f"], ["yy",
"gg"], ["zzz"]] 

我正在考虑使用结构节点中的 void 指针来存储另一个列表,即主列表的每个节点中的列表。但我不断收到以下错误

dereferencing 'void *' pointer

我也尝试过类型转换。可能还有其他问题,但由于上述问题,我还没有到达那里。

typedef struct Node {
    void *value;
    struct Node *next; // self-reference
} Node;

// Group elements in list. Equivalent elements (for which equivalent is true) are put
// in the same group. The result is a list of groups. Each group is itself a list.
// Each group contains items that are equivalent.

Node *group_list(Node *list, EqualFun equivalent) {
    
    Node *list_new = malloc(sizeof(Node));
    //list_new = NULL;
    list_new->next = NULL;
    (Node *)list_new->value = malloc(sizeof(Node));
    (char *)(list_new->value->value) = list->value;
    list_new->value->next = NULL;
    Node *temp1 = list->next;
    
    Node *list_tester1 = list_new;
    Node *list_tester2 = list_new;
    
    while (list_new != NULL) {
        
        while (temp1 != NULL) {  //for the list inside list_new
            list_tester2 = list_tester1;
            if (equivalent(list_new->value->value, temp1->value)) {
                list_new->value = append_list(list_new->value, temp1->value);
            } else {     
                while (list_tester2 != NULL) { // for outer list
                    if (!equivalent(list_tester2->value->value, temp1->value)) {
                        list_new = append_list(list_new->value, temp1->value);
                        list_new = append_list(list_tester2->value, temp1->value);
                        list_new = append_list(list_tester1->value, temp1->value);       
                    }        
                    list_tester2 = list_tester2->next;   
                }
            }
            list_new = list_new->next;
        }
    }
    return list_new;
}

【问题讨论】:

  • void* 是一个指针,它指向一个不完整类型的对象。您不能取消引用 void* 指针。编译器无法确定结果类型。例如。 list_new->value->next=NULL; 取消引用 valuevoid* (这在您的代码中多次完成)。在使用(char *)(list_new->value->value)=list->value; 取消引用之前,您在该声明之上 - 这仅部分解决了需要类似于((char *)(list_new->value)->value=list->value; 的问题使用void* 很好,但要了解限制。

标签: c list recursion casting void-pointers


【解决方案1】:

如果在编译时已知最大字长(以及因此子列表的最大数量),您可以创建一个指向各个子列表头部的指针数组。数组的第一个元素将指向长度为 1 的单词的子列表,数组的第二个元素将指向长度为 2 的单词的子列表,依此类推。

如果您想使用链表的链表(即嵌套链表),则必须创建两种类型的节点。一种节点用于主链表,一种节点用于子链表。

例如,您可以定义以下两个结构:

struct SubListNode
{
    char *word;
    struct SubListNode *next;
};

struct MainListNode
{
    struct SubListNode *head_of_sublist;
    struct MainListNode *next;
};

我认为在这种情况下没有理由使用 void 指针,因为被引用对象的类型总是已知的。

虽然两个列表可以通过使用 void 指针共享相同的 struct,因此您只需声明一个 struct,但我认为这样做没有任何好处。每当取消引用 void 指针时,您都必须将其转换为它所指向的适当类型。这将使您的代码比简单地声明第二种类型的struct 复杂得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 2013-05-09
    • 1970-01-01
    • 2010-11-14
    • 1970-01-01
    • 2014-10-01
    相关资源
    最近更新 更多