C语言写的一个容器list

今天无聊用C语言写了一个容器list,我发现现在微软的vs2010已经很规范的处理C语言的编译工作了。比如说变量声明必须在函数最前面,声明一个struct变量的时候必须加上struct关键字等等。
扩展性:为了让这个list支持任意类型,list中的节点存储两个变量:一个是用户自定义的类型的对象的地址,一个是next指针。一开始我想把操作都封装起来,全部声明为静态的,然后在operations结构体中放入指向这些静态函数的指针。但是后来一想这样其实也没多大必要,因为我必须定义一个形参,这个形参为当前的list。所以干脆就把这些操作暴露给用户。
与其写出
list animals
animals.oprs.insert(&animals,&eliphant);这样的代码
还不如写出
list animals
listinsert(&animals,&eliphant);

内存管理:其实内存管理是一项非常有意思的工作,但是这里我只是简单的处理了一下,没有实现什么内存池啥的。对于内存管理当然要遵循谁申请谁释放的原则了。node是不能暴露给用户的。
遍历操作:遍历操作需要用户自己写一个回调函数实现自己想要的那套处理方法。列表的插入删除操作啥的这个仁者见仁智者见智了。我的插入操作时在链表头插入。

#ifndef LIST_H
#define LIST_H
#include <stdio.h>
#include <malloc.h>

#ifdef __cplusplus
extern "C"{
#endif

struct list;
struct node;
struct operations;/*废弃*/

typedef struct node{
    unsigned int value;
    struct node* next;
}node,*nodeptr;

typedef struct operations{
    void (*insert)(struct list *l , void* p);
    void (*remove)(struct list *l , void* p);
    void (*traverse)(struct list *l , void (*callback)(void*));
}operations,*operaptr;

typedef struct list{
    nodeptr head;
    int length;
}list;

void listinit(struct list* l);
void listinsert(struct list *l , void* p);
void listremove(struct list *l , void* p);
void listtraverse(struct list *l , void(*callback)(void*));
int listlength(struct list *l);

static    nodeptr listnewnode();

#ifdef __cplusplus
}
#endif

#endif

#include "list.h"

static operations ops={    listinsert,
    listremove,
    listtraverse,
};

void listinit(list* l)
{
    (*l).head=NULL;
    (*l).length=0;
}

void listinsert(list *l , void *thisnode)
{
    nodeptr p=listnewnode();
    p->value=(unsigned int)thisnode;
    p->next=(*l).head;
    (*l).head=p;
    (*l).length+=1;
}

void listremove(list *l , void *thisnode)
{
    nodeptr head;
    nodeptr prev;
    prev=(*l).head;
    if(prev==NULL){
        printf("This list is NULL\n");
        return ;
    }
    if(thisnode==NULL){
        printf("this node is NULL\n");
        return ;
    }
    if(prev->value==(unsigned int)thisnode){
        (*l).head=(*l).head->next;
        free(prev);
        (*l).length-=1;
    }else{
        for(head=(*l).head ; head!=NULL ; head=head->next){
            if((unsigned int)thisnode==head->value){
                prev->next=head->next;
                free(head);
                (*l).length-=1;
                break;
            }
            prev=head;
        }
        if(head==NULL){
            printf("This list has no this node\n");
        }
    }
}

nodeptr listnewnode()
{
    return (nodeptr)malloc(sizeof(node));
}
/************************************************************************/
/* if you wanna do something to the node, please write a callback. it   */
/* must has the type of void(*callback)(void*)                          */
/************************************************************************/
void listtraverse(list *l , void(*callback)(void*))
{
    nodeptr head=(*l).head;
    for( ; head!=NULL ; head=head->next)
        callback((void*)(head->value));
}

int listlength(list *l)
{
    return (*l).length;
}

下面给出一个测试用的代码

#include <stdio.h>
#include <stdlib.h>
#include "list.h"


typedef struct monkey{
    int age;
    int master;
    int code;
}monkey;

void callback(void *param)
{
    monkey *thismonkey=(monkey*)param;
    int sum=thismonkey->age+thismonkey->master+thismonkey->code;
    printf("%d,%d,%d,SUM:%d\n",thismonkey->age,thismonkey->master,thismonkey->code,sum);
}

int main(int argc ,char *argv[])
{
    list animals;
    monkey jack;
    monkey rose;
    monkey tom;
    monkey *p;
    listinit(&animals);
    jack.age=20;
    jack.master=20;
    jack.code=20;

    rose.age=21;
    rose.master=21;
    rose.code=21;

    tom.age=22;
    tom.master=22;
    tom.code=22;
    listinsert(&animals,&jack);
    listinsert(&animals,&rose);
    listinsert(&animals,&tom);
    listtraverse(&animals,callback);

    listremove(&animals,NULL);

    listtraverse(&animals,callback);
    printf("%d\n",listlength(&animals));

    system("pause");
    return EXIT_SUCCESS;
}
其实我一直都持有这种想法,C语言能实现一切的东西,因为可以直接操作内存嘛。

### 回答1: STL(Standard Template Library)是 C++ 语言的标准模板库,而不是 C 语言。因此,如果您想在 C 语言中使用 STL 的 list,您可以一个类似的数据结构,例如链表。 下面是一个简单的链表实现: ``` #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next; } Node; Node *create_node(int data) { Node *new_node = (Node *)malloc(sizeof(Node)); new_node->data = data; new_node->next = NULL; return new_node; } void insert_node(Node **head, int data) { Node *new_node = create_node(data); new_node->next = *head; *head = new_node; } void print_list(Node *head) { Node *current = head; while (current != NULL) { printf("%d ", current->data); current = current->next; } printf("\n"); } int main() { Node *head = NULL; insert_node(&head, 1); insert_node(&head, 2); insert_node(&head, 3); print_list(head); return 0; } ``` 输出结果为: ``` 3 2 1 ``` 请注意,这只是一个简单的链表实现,并不是 STL 的 list 的完整实现,但它可以作为您开始学习链表的一个起点。 ### 回答2: 在C语言中实现一个类似STL的list可以通过使用指针和结构体来完成。下面是一个简单的示例: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node* next; struct Node* prev; } Node; typedef struct { Node* head; Node* tail; } List; List* createList() { List* list = (List*)malloc(sizeof(List)); list->head = NULL; list->tail = NULL; return list; } void insert(List* list, int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = NULL; newNode->prev = NULL; if (list->head == NULL) { // Inserting into an empty list list->head = newNode; list->tail = newNode; } else { // Inserting at the end of the list list->tail->next = newNode; newNode->prev = list->tail; list->tail = newNode; } } void display(List* list) { Node* current = list->head; while (current != NULL) { printf("%d ", current->data); current = current->next; } printf("\n"); } int main() { List* list = createList(); insert(list, 10); insert(list, 20); insert(list, 30); display(list); return 0; } ``` 上述代码使用了两个结构体,Node表示每个节点,List表示整个链表。函数createList()用于创建一个新的链表,insert()函数用于将元素插入到链表的末尾,display()函数用于显示链表中的所有元素。 在main()函数中,我们创建了一个新的链表,然后插入了三个元素,最后调用display()函数显示链表中的所有元素。输出结果为:10 20 30。这个简单的C语言示例实现了最基本的链表操作,你可以根据需要进一步扩展功能,实现更完整的STL list。 ### 回答3: C语言是一种非面向对象的编程语言,因此它不直接支持STL(标准模板库)的容器,比如list。不过我们可以通过使用指针和动态内存分配来实现类似于list的数据结构。 要实现一个类似于STL的list,我们可以创建一个结构体来表示list的节点,其中包含一个数据成员和两个指针成员,分别指向前一个节点和后一个节点。同时,我们还需要定义一些用于操作list的函数。 首先,我们需要定义一个创建list节点的函数,它接受一个数据作为参数,并返回指向创建节点的指针。代码如下所示: ``` typedef struct ListNode { int data; struct ListNode* prev; struct ListNode* next; } ListNode; ListNode* createNode(int data) { ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); newNode->data = data; newNode->prev = NULL; newNode->next = NULL; return newNode; } ``` 接下来,我们可以定义一个结构体来表示list本身,其中包含指向第一个节点和最后一个节点的指针。我们还可以定义一些用于操作list的函数,比如插入节点、删除节点、获取list长度等。这些函数可以根据具体需求进行实现。 以下是一个简单的示例代码,演示了如何使用C语言来实现类似于STL的list: ``` typedef struct List { ListNode* head; ListNode* tail; } List; void insertNode(List* list, int data) { ListNode* newNode = createNode(data); if (list->head == NULL) { list->head = newNode; list->tail = newNode; } else { newNode->prev = list->tail; list->tail->next = newNode; list->tail = newNode; } } void deleteNode(List* list, int data) { ListNode* currentNode = list->head; while (currentNode != NULL) { if (currentNode->data == data) { if (currentNode->prev != NULL) { currentNode->prev->next = currentNode->next; } else { list->head = currentNode->next; } if (currentNode->next != NULL) { currentNode->next->prev = currentNode->prev; } else { list->tail = currentNode->prev; } free(currentNode); break; } currentNode = currentNode->next; } } int getListLength(List* list) { int length = 0; ListNode* currentNode = list->head; while (currentNode != NULL) { length++; currentNode = currentNode->next; } return length; } ``` 通过以上代码,我们可以实现一个简单的类似于STL的list,它包含插入节点、删除节点和获取list长度等操作。当然,这只是一个简单的实现示例,实际使用时还可能需要考虑更多的细节和功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值