【问题标题】:How to use unknow data types in C如何在 C 中使用未知数据类型
【发布时间】:2014-02-23 20:12:50
【问题描述】:

下面是我的代码,它为 C 中的链接列表提供了一个简单的接口。因此它的行为类似于 java 中的 ArrayLists。

我的问题是这样的:

我的代码只适用于希望拥有整数链接列表的人。

我知道他们可以使用 int 通过指针来保存其数据类型的地址。

但是,我想要更通用的东西。

我可以在节点结构中使用 void* 代替 int 吗?那么用户可以提供int、double、char等...?

代码:

#include <stdio.h>

#include <stdlib.h>

int AL_appened(int val);
struct Tuple AL_find(int val);
int AL_remove(int val);
int AL_setup();
int AL_len();

typedef struct Node Node;
typedef struct Tuple Tuple;

struct Node{

    int val;

    Node *next;

};

struct Tuple{
    int index;
    int val;
};

Node *root, *curr;


int AL_appened(int val) {
    Node *tmp;
    tmp = (Node *)malloc(sizeof (Node));
    curr->next = tmp;
    tmp->val = val;
    curr = tmp;
    root->val++;
    return 0;

}



struct Tuple AL_find(int val){
    if(root->next) {
     curr = root->next;

        int count = 0;
        while (curr->next){

            if (curr->val == val){
                Tuple r = {count+=1, val};
                return r;
            }
            count++;
            curr = curr->next;

        }
        if (curr->val == val){
            Tuple r = {count+=1, val};
            return r;
        }
    }
        Tuple r = {-1, -1};
        return r;

}



int AL_remove(int val){
    Node *prev;
    prev = (Node *)malloc(sizeof (Node));
    curr = root;
    while (curr->next->val != val){
        prev = curr;
        curr = curr->next;
    }
    if (curr->next->val != val) return -1;
        curr->next = curr->next->next;
    root->val--;
    free(curr->next);
    return 1;

}


int AL_setup(){
    root = (Node *)malloc(sizeof(Node));
    root->val = 0;
    root->next = 0;
    curr = root;
    return 0;

}

int AL_len(){
    return root->val;
}

void printAll(){
    curr=root->next;
    while (curr->next != NULL) {
        printf("%d\n",curr->val);
        curr=curr->next;
    }
    printf("%d\n",curr->val);
}

int main(){
    AL_setup(); //setup the root, we will use root to keep track of the number of links
    AL_appened(1); // append 1 so it should look like root>1
    AL_appened(2); // append 2 so it should look like root>1>2
    AL_appened(3);
    AL_appened(4);
    printf("%d\n", AL_len()); // print len of list

    Tuple results = AL_find(4); // find 4 in list
    printf("%d %d\n", results.index, results.val); // return the index and the number found

    AL_remove(3);
    Tuple results2 = AL_find(4);
    printf("%d %d\n", results2.index, results2.val);

    results2 = AL_find(4);
    printf("%d %d\n", results2.index, results2.val);
    printAll(); // print entire list
    return 0;
}

【问题讨论】:

  • Doorknob:就在我投票给你的时候...... ;) C 没有模板,是吗?
  • @Doorknob 或禁言类型!但这是 C。
  • @Constantinius 哎呀,很抱歉忽略了标签:P(当我对 C++ 几乎一无所知时,我也试图回答它:P)
  • 检查 klib.sourceforge.net 是否使用宏替代 void*

标签: c


【解决方案1】:

好吧,您可以将 void* 作为值类型,但这需要为每个节点分配额外的内存。我见过的另一种方法是仅将链接放在结构中,并让用户声明自己的节点类型(首先使用链接),然后转换为通用节点类型。我什至见过将链表库放入预处理器宏中,例如 DEFINE_LINKED_LIST(Foo) 生成 FooListFooNodeappendFoo 函数等。最后,您可以放入所有您认为的类型 可能想要加入一个联合的价值。

最终,没有特别干净、漂亮的方法可以做到这一点; C 不太适合多态性。您需要决定最喜欢哪个不完美的选项。

【讨论】:

    【解决方案2】:

    linux 程序员也有类似的问题,他们想出了一个通用的解决方案。简而言之,他们的方法是定义一个list_head 结构,将其插入需要成为链表一部分的任何用户结构中。由于包含与您的代码中的相反,因此链表实现 1. 不会以任何方式限制用户结构,并且 2. 允许用户结构成为多个链表的成员。这确实是一个非常灵活的设计,并且由于它是 GPL 的,您可以在任何 GPL 代码中使用它。

    This 对 SO 上另一个问题的回答指向内核列表的用户空间适应。我自己没有测试过,所以使用它需要您自担风险。不过看起来很正常。)

    【讨论】:

      猜你喜欢
      • 2020-09-13
      • 2019-08-14
      • 1970-01-01
      • 2016-11-28
      • 2022-07-20
      • 1970-01-01
      • 2016-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多