简单的基于sqlite的服务器和客户端实现

server.c

c 复制代码
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/epoll.h>
#include "doublyList.h"
#include <sqlite3.h>
#include "array.h"
myListOP * fdList;


int isSameAddr(void* a,void*b){
    return a-b;
}
int isSameInt(int* a,int*b){
    return *a-*b;
}



struct info{
    struct sockaddr_in client_addr;
    int fd;
    struct epoll_event* event;
    myListOP* record;
};

int* getfd(struct info* info){
    return &(info->event->data.fd);
}




struct patientRecord
{
    time_t time;
    char patientName[40];
    char patientRec[128];
    char doctorDia[128];
    char tablet[128];
    char doctorAdv[128];
    //size=4*128+4+40=556
};
struct patientRecord * createPatinetRecord(time_t time,char* patientName,\
                        char* patientRec,char* doctorDia,char* tablet,char* doctorAdv){
                           struct patientRecord * ret = malloc (sizeof (struct patientRecord));
                           ret->time = time;
                           if (patientName)
                           {
                            strcpy(ret->patientName,patientName);
                           }
                           strcpy(ret->patientRec,patientRec);
                           strcpy(ret->doctorDia,doctorDia);
                           strcpy(ret->tablet,tablet);
                           strcpy(ret->doctorAdv,doctorAdv);
                           return ret;
                        }
enum enum_send_t{
    send_record =1,
    read_record,
};
struct send_t
{
    enum enum_send_t type;
    struct patientRecord patientRecord;
};
static void printRec(struct patientRecord* rec){
    char timeStr[64]; // 用于存储格式化后的时间字符串
    strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", localtime(&rec->time));
    printf("%s::\n 病人描述:%s\n, 医生诊断:%s\n, 开药:%s\n, 医嘱:%s\n",
           timeStr, rec->patientRec, rec->doctorDia, rec->tablet, rec->doctorAdv);
}
static void printSend_t(struct send_t* send){
    if (send->type == send_record)
    {
        printf("send_record\n");
    }
        if (send->type == read_record)
    {
        printf("read_record\n");
    }

    printRec(&send->patientRecord);
}

struct info* creatInfo(struct sockaddr_in *client_addr,int fd,struct epoll_event* event){
    struct info* ret = malloc(sizeof(struct info));
    ret->record = myListDInit(printSend_t);
    if (client_addr)
    {
        ret->client_addr=*client_addr;
    }
    else{
        memset(&ret->client_addr,0,sizeof(struct sockaddr_in));
    }
    ret->event = event;
    ret->fd = fd;
    return ret;
}
void printInfo(struct info* info){
    static char ip_human[16] = {0};
    if (info ==0 || (&(info->client_addr)==0))
    {
        return;
    }
    
    int port_human=ntohs(info->client_addr.sin_port);
    inet_ntop(AF_INET,&info->client_addr.sin_addr,ip_human,16);
    printf("ip:%s,port:%d,fd:%d::",ip_human,port_human,info->fd);
}

sqlite3* db;

int mysqlite3_append(struct patientRecord* rec){
    char sql[1024]="";
    sprintf(sql,"create table if not exists %s (\
        日期 INTEGER ,\
        病人口述 TEXT,\
        医生诊断 TEXT,\
        医生开药 TEXT,\
        医嘱 text \
        );", rec->patientName);
    char ** result;
    char * errmsg;
    int ret = 0;
    ret=sqlite3_exec(db,sql,0,0,&errmsg);
    if (ret)
    {
        //sql执行一场
        printf("在添加表格时出现异常:: %s\n",errmsg);
        return EXIT_FAILURE;
    }
    sprintf(sql,"insert into %s (日期,病人口述,医生诊断,医生开药,医嘱)\
        values (%ld,'%s','%s','%s','%s');",\
        rec->patientName,rec->time,rec->patientRec,rec->doctorDia,rec->tablet,rec->doctorAdv);
    ret=sqlite3_exec(db,sql,0,0,&errmsg);
    if (ret)
    {
        //sql执行一场
        printf("在添加数据时出现异常:: %s\n",errmsg);
        return EXIT_FAILURE;
    }
    return 0;
}
int callback (myListOP* list,int argc, char ** argv,char** col){
    // for (int i = 0; i < argc; i++)
    // {
    //     /* code */
    // }

    list->append(list,createPatinetRecord(atol(argv[0]),0,argv[1],\
                argv[2],argv[3],argv[4]));
    return 0;
    
}
int mysqlite3_read(struct patientRecord * rec,myListOP* list){
    char sql[1024]="";
    
    sprintf(sql,"create table if not exists %s (\
        日期 INTEGER ,\
        病人口述 TEXT,\
        医生诊断 TEXT,\
        医生开药 TEXT,\
        医嘱 text \
        );", rec->patientName);
    char ** result;
    char * errmsg;
    int ret = 0;
    ret=sqlite3_exec(db,sql,0,0,&errmsg);
    if (ret)
    {
        //sql执行一场
        printf("在添加表格时出现异常:: %s\n",errmsg);
        return EXIT_FAILURE;
    }
    sprintf(sql,"select * from %s ;", rec->patientName);
    ret=sqlite3_exec(db,sql,callback,list,&errmsg);
    if (ret)
    {
        //sql执行一场
        printf("在添加数据时出现异常:: %s\n",errmsg);
        return EXIT_FAILURE;
    }
    return 0;
}
int serverfun(struct info* info){
    int client = info->fd;
    char ip_human[16]={0};
    int port_human=0;
    struct sockaddr_in client_addr = {0};
    client_addr = info->client_addr;
    inet_ntop(AF_INET,&client_addr.sin_addr,ip_human,16);
    port_human=ntohs(client_addr.sin_port);
    char buf[560] = "";
    int res = read(client,buf,sizeof(unsigned short int));
    int size = *(unsigned short int*)buf;
    if (res == 0)
    {
        printf("客户端已断开连接:\nIP:%s\nport:%d\n",ip_human,port_human);
        close(client);
        fdList->del(fdList,fdList->find(fdList,info,0));
        return 0;
    }
    res = read(client,buf+sizeof(unsigned short int),size-sizeof(unsigned short int));
    myListOP * tmp =0;
    tmp = info->record->unpack(info->record,buf,printRec);
    info->record->destory(info->record);
    info->record=tmp;
    struct send_t * st = 0;
    unsigned int i=0;
    while (st = info->record->slice(info->record,i++))
    {
        if (st->type == send_record)
        {
            mysqlite3_append(&st->patientRecord);
        }
        if (st->type == read_record)
        {
            myListOP* list = myListDInit(printRec);
            mysqlite3_read(&st->patientRecord,list);
            while (list->packed == 0)
            {
                res = list->pack(list,buf,560,sizeof(struct patientRecord));
                send(info->fd,buf,res ,0);
            }
            list->destory(list);
        }
        
    }
    return 1;
}
void printEvent(struct epoll_event event){
    printf("fd:%d,ptr:%p-->",event.data.fd,event.data.ptr);
}

int main(int argc, char const *argv[])
{
    if (argc<2)
    {
        printf("请输入端口号\n");
        return 1;
    }
    
    int server = socket(AF_INET,SOCK_STREAM,0);
    sqlite3_open("/home/mr-oy/c-codes/数据库/hospital.db",&db);
    struct sockaddr_in addr={0};
    addr.sin_family=AF_INET;
    addr.sin_port=htons(atoi(argv[1]));
    addr.sin_addr.s_addr=inet_addr("0.0.0.0");

    if(bind(server,(struct sockaddr * )&addr,sizeof(addr))==-1){
        perror("bind:");
        return 1;
    }
    struct sockaddr_in client_addr = {0};
    int client_len = sizeof(client_addr);

    int ret;
    int max = 10;
    listen(server,max);
    char ip_human[16]="";
    int port_human = 0;
    //创建监视列表
    int epoll_handler = epoll_create1(EPOLL_CLOEXEC);
    // 将服务器加入到handeler内
    struct epoll_event serverEvent;
    serverEvent.events=EPOLLIN|EPOLLET;
    serverEvent.data.fd=server;
    epoll_ctl(epoll_handler,EPOLL_CTL_ADD,server,&serverEvent);

    int client;
    fdList = myListDInit((void(*)(void*))printInfo);
    struct info * currentinfo=0;
    struct epoll_event* currentevent=0;
    int* currentfd =0;
    unsigned int i=0;

    // fdList->append(fdList,creatInfo(0,server,&serverEvent));
    myArrayOP* eventList = myArrayInit(20,sizeof(struct epoll_event),printEvent);

    printf("服务器正在运行:\n");
    for (;;)
    {
        i=0;
        memset(eventList->data,0,eventList->max_length*eventList->size);
        eventList->length = epoll_wait(epoll_handler,eventList->data,eventList->max_length,-1);
        while (currentevent = (struct epoll_event*)eventList->slice(eventList,i++))
        {
            currentfd = &(currentevent->data.fd);
            if (*currentfd == server)//有新的客户端连接
            {
                client = accept(server,(struct sockaddr * )&client_addr,&client_len);
                struct epoll_event* clientevent = malloc(sizeof(struct epoll_event)) ;
                memset(clientevent,0,sizeof(struct epoll_event));
                clientevent->data.fd=client;
                clientevent->events=EPOLLIN|EPOLLET;
                fdList->append(fdList,creatInfo(&client_addr,client,clientevent));
                epoll_ctl(epoll_handler,EPOLL_CTL_ADD,client,clientevent);
                inet_ntop(AF_INET,&client_addr.sin_addr,ip_human,16);
                port_human=ntohs(client_addr.sin_port);
                printf("客户端已连接:\nIP:%s\nport:%d\n",ip_human,port_human);
                //将该fd添加到epoll
                continue;;
            }
            //客户端操作
            else if (*currentfd != server)
            {
                unsigned int index= fdList->findby(fdList,isSameInt,getfd,currentfd,0);
                // fdList->print(fdList);
                currentinfo = fdList->slice(fdList,index);
                serverfun(currentinfo);
            }
            
        }
        
        
        

    }  
    return 0;
}

client.c

c 复制代码
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <wait.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/un.h>
#include "doublyList.h"
#include "array.h"
struct patientRecord
{
    time_t time;
    char patientName[40];
    char patientRec[128];
    char doctorDia[128];
    char tablet[128];
    char doctorAdv[128];
    //size=4*128+4+40=556
};
enum enum_send_t{
    send_record =1,
    read_record,
};
struct send_t
{
    enum enum_send_t type;
    struct patientRecord patientRecord;
};

struct send_t * createSend_t(enum enum_send_t type,time_t time,char* patientName,\
                        char* patientRec,char* doctorDia,char* tablet,char* doctorAdv){
                           struct send_t * st = malloc (sizeof (struct send_t));
                           st->type = type;
                           struct patientRecord *ret = &st->patientRecord;
                           memset(ret,0,sizeof(struct patientRecord));
                           ret->time = time;
                           strcpy(ret->patientName,patientName);
                           if (patientRec !=0)
                           {

                            strcpy(ret->patientRec,patientRec);
                            strcpy(ret->doctorDia,doctorDia);
                            strcpy(ret->tablet,tablet);
                            strcpy(ret->doctorAdv,doctorAdv);
                           }
                           
                           return st;
                        }

static void printRec(struct patientRecord* rec){
    char timeStr[64]; // 用于存储格式化后的时间字符串
    strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", localtime(&rec->time));
    printf("%s::\n 病人描述:%s\n, 医生诊断:%s\n, 开药:%s\n, 医嘱:%s\n",
           timeStr, rec->patientRec, rec->doctorDia, rec->tablet, rec->doctorAdv);
}
static void printSend_t(struct send_t* send){
    if (send->type == send_record)
    {
        printf("send_record\n");
    }
        if (send->type == read_record)
    {
        printf("read_record\n");
    }

    printRec(&send->patientRecord);
}
int main(int argc, char const *argv[])
{
    if (argc<3)
    {
        printf("请输入端口号\n");
        printf("请输入模式\n");
        return 1;
    }
    char patientName[40];
    char patientRec[128];
    char doctorDia[128];
    char tablet[128];
    char doctorAdv[128];

    
    myListOP* list = myListDInit(printSend_t);

    int clinet = socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in addr={0};
    addr.sin_family=AF_INET;
    addr.sin_port=htons(atoi(argv[1]));
    addr.sin_addr.s_addr=inet_addr("127.0.0.1");

    char buf[560] = {0};
    int used =0;

    if(connect(clinet,(struct sockaddr*)&addr,sizeof(addr))==-1){
        perror("connect:");
        return 1;
    }
    if (strcmp(argv[2],"-u"))
    {
    for (;;)
    {
        
        printf("请输入病人姓名\n");
        scanf(" %s",patientName);
        printf("请输入病人自述\n");
        scanf(" %s",patientRec);
        printf("请输入医生诊断\n");
        scanf(" %s",doctorDia);
        printf("请输入药物\n");
        scanf(" %s",tablet);
        printf("请输入医嘱\n");
        scanf(" %s",doctorAdv);

        list->append(list,createSend_t(send_record,time(NULL),\
        patientName,patientRec,doctorDia,tablet,doctorAdv
        ));
        used = list->pack(list,buf,560,560);
        write(clinet,buf,used);
    }  
    }
    else{
    for (;;)
    {
        
        printf("请输入病人姓名\n");
        scanf(" %s",patientName);
        list->append(list,createSend_t(read_record,0,\
        patientName,0,0,0,0
        ));
        used = list->pack(list,buf,560,560);
        write(clinet,buf,used);
        while (1)
        {
            used = read(clinet,buf,sizeof(unsigned short int));//理论上会卡死在这行,回头优化
            int size = *(unsigned short int*)buf;
            used = read(clinet,buf+sizeof(unsigned short int),size-sizeof(unsigned short int));
            myListOP * tmp =0;
            tmp = myListDUnpack(0,buf,printRec);
            tmp->print(tmp);
        }
        
        
        
        
    }  
    }
    
    
    return 0;
}

依赖:

doublyLIst.c

c 复制代码
#include "doublyList.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static int isNull(myListOP * self){
    return self==0 || self->data==0;//头的位置是空,则为null
}
static int isEmpty(myListOP * self){
    return self->data->next==0||self->data->data==0;//头的data的指针指向自己则为null
}
static int isNullOrEmpty(myListOP * self){
    return isNull(self)||isEmpty(self);
}
static void* dequeue(myListOP * self){
    void * ret=0;
    if (isNullOrEmpty(self))
    {
        return 0;
    }
    if (self->data->next == self->data) //只有一个的情况下
    {
        self->length--;
        ret = self->data->data;
        self->data->data =0;
        return ret;
    }
    

    myListP head =self->data;
    head->prev->next = head->next;
    head->next->prev=head->prev;
    self->data=head->next;
    ret = head->data;

    self->__head =0; //迭代器重新生成
    self->length--;
    free(head);
    return ret;
}
static void *pop(myListOP * self){
    if (isNullOrEmpty(self))
    {
        return 0;
    }
    void*ret;
    if (self->data->next == self->data) //只有一个的情况下
    {
        self->length--;
        ret = self->data->data;
        self->data->data =0;
        return ret;
    }
    self->length--;
    self->__head=0;//迭代器重新生成
    myListP current=self->data;
    myListP prev=0;
    myListP next=0;
    
    current = current->prev;//定位到尾部
    prev=current->prev;
    next=current->next;

    prev->next=next;
    next->prev=prev;

    ret=current->data;
    current->data=0;
    free(current);
    return ret;
}

static myListP slice (myListOP * self,unsigned int i){
    if (isNullOrEmpty(self)) //判断是否为空
    {
        return 0;
    }
    //期待i在0~.length之间
    //区间分成了三段,0,__index,length,查看i离哪个更近
    unsigned int distanceFromHead = i;
    unsigned int distanceFromTail = self->length - i;
    unsigned int distanceFromCurrent = i - self->__index;
    distanceFromCurrent=distanceFromCurrent>0?distanceFromCurrent:-distanceFromCurrent;
    if (distanceFromHead <= distanceFromTail && distanceFromHead <= distanceFromCurrent)
    {
        //i离头更近,从头开始遍历
        self->__index = 0;
        self->__last = self->data;
        self->__head = self->data;
    }
    else if (distanceFromTail < distanceFromHead && distanceFromTail <= distanceFromCurrent)
    {
        //i离尾更近,从尾开始遍历
        self->__index = self->length - 1;
        self->__last = self->data->prev;
    }
    if (self->__head != self->data)
    {
        self->__index =0;
        self->__last = self->data;
        self->__head=self->data;
    }
    if (i == 0)
    {
        return self->data;
    }
    for ( ; self->__index < i; self->__index++)
    {
        self->__last = self->__last->next;
        if (self->__last == self->__head)
        {
            break;
        }
        
    }
    for (; self->__index > i; self->__index--)
    {
        self->__last = self->__last->prev;
        if (self->__last == self->__head)
        {
            break;
        }
    }
    return self->__last == self->data?0:self->__last;
}
static void* _slice(myListOP * self,unsigned int i){
    // 这里是后实现的,为了避免对内部函数进行重构,未对slice方法进行重命名
    // 实际用户使用的slice应当为_slice
    // 使用的_slice应当为slice
    // 2025/5/9 修复可能的段错误
    myListP obj = slice(self,i);
    return obj?obj->data:obj;
}
static void*del(struct myListOP*self,unsigned int where){
    if (isNullOrEmpty(self))
    {
        return 0;
    }
    if (where == 0)
    {
        return dequeue(self);
    }
    if (where == self->length-1)
    {
        return pop(self);
    }
    
    //存在2个以上的元素
    myListP last=slice(self,where-1);
    myListP current=slice(self,where);
    myListP next=slice(self,where+1);
    void * ret=0;
    last->next=next;
    next->prev=last;
    ret=current->data;
    free(current);
    self->length --;
    self->__head =0;//迭代器重新生成
    return ret;
}
static int _insertHead(struct myListOP*self,void* data){
    if (isNull(self))
    {
        return 0;
    }
    if (self->data->data ==0)
    {
        self->data->data=data;
        self->__head =0;//迭代器
        self->length++;
        return 1;
    }
    myListP current=(myListP) malloc(sizeof(myList));
    current->data=data;
    current->next=self->data;
    current->prev=self->data->prev;
    self->data->prev->next=current;
    self->data->prev=current;
    self->length++;
    // self->data->prev->next=current;
    self->data=current; //迭代器重新生成
    return 1;
}
static int append(struct myListOP*self,void* data){
    if (isNull(self))
    {
        return 0;
    }
    if (self->data->data ==0)
    {
        self->data->data=data;
        self->__head =0;//迭代器
        self->length++;
        return 1;
    }
    
    myListP current=(myListP) malloc(sizeof(myList));
    myListP head = self->data;
    current->data=data;
    current->next=head;
    current->prev=head->prev;
    head->prev->next=current;
    head->prev=current;
    self->__head =0;//迭代器
    self->length++;
    return 1;
}
static int insert(struct myListOP*self,unsigned int where,void* data){
    if (isNull(self))
    {
        return 0;
    }
    if (where ==0 )
    {
        return _insertHead(self,data);
    }
    if (where ==self->length )
    {
        return append(self,data);
    }
    
    myListP last=slice(self,where-1); //最小 where =1
    myListP current=(myListP) malloc(sizeof(myList));
    myListP next=slice(self,where);

    current->data=data;

    current->next=next;
    current->prev=last;
    last->next=current;
    next->prev=current;
    self->__head =0;
    self->length++;
    return 1;
}
static int delAll(struct myListOP*self,unsigned int where){
    void * data = del(self,where);
    if (data)
    {
        free(data);
        return 1;
    }
    return 0;
}

static unsigned int find(struct myListOP*self,void* obj,unsigned int times){
    myListP p =0;
    unsigned int count =0;
    for (unsigned int i = 0; i < -1; i++)
    {
        p=slice(self,i);
        if (p==0)
        {
            break;
        }
        if (p->data==obj)
        {
            if (times == count)
            {
                return i;
            }
            count ++;
        }

    }
    return -1;
}
static unsigned int findby(struct myListOP*self,int(*cmp)(void*,void*),void*(*filed)(void*),void*target,unsigned int times){//cmp应该返回是否是要找的值
    myListP p =0;
    unsigned int count =0;
    for (unsigned int i = 0; i < -1; i++)
    {
        p=slice(self,i);
        if (p==0)
        {
            break;
        }
        if (cmp(filed(p->data),target)==0)
        {
            if (times == count)
            {
                return i;
            }
            count ++;
        }
    }
    return -1;
}
static unsigned int unicNoFree (struct myListOP*self,void*(*field)(void*),long unsigned int size,unsigned int times){
    unsigned int count=0;
    unsigned int ret =0;
    for (unsigned int i = 1; i < self->length; i++)
    {
        count =0;
        for (unsigned int j = i+1; j < self->length; j++)
        {
            if (memcmp(field(slice(self,i)->data),field(slice(self,j)->data),size)==0)
            {
                if (count >= times)
                {
                    self->delNoFree(self,j);
                    j=j-1;
                }
                count=count+1;
                ret = ret+1;
            }
        }
    }
    return ret;
}
static unsigned int unic (struct myListOP*self,void*(*field)(void*),long unsigned int size,unsigned int times){
    unsigned int count=0;
    unsigned int ret =0;
    for (unsigned int i = 1; i < self->length; i++)
    {
        count =0;
        for (unsigned int j = i+1; j < self->length; j++)
        {
            if (memcmp(field(slice(self,i)->data),field(slice(self,j)->data),size)==0)
            {
                if (count >= times)
                {
                    self->del(self,j);
                    j=j-1;
                }
                count=count+1;
                ret = ret+1;
            }
        }
    }
    return ret;
}

static void print(struct myListOP*self){


    // for (unsigned int i = 0; i < self->length; i++)
    // {
    //     self->__str(self->slice(self,i)->data);
    // }
    myListP cur=self->data;
    if (isNullOrEmpty(self))
    {
        return;
    }
    do{
        self->__str(cur->data);
        cur=cur->next;
    }while (cur!=self->data);
    
    printf("\n");
}

static void destory (myListOP *self){
    for (unsigned int i = 0; i < self->length; i++)
    {
        self->del(self,0);
    }
    free(self->data);
    self->data=0;
    free (self);
}
static void destoryNoFree (myListOP *self){
    for (unsigned int i = 0; i < self->length; i++)
    {
        del(self,0);
    }
    // free(self->data);
    self->data=0;
    free (self);
}
static void _quickSort(myListOP *self,long int start,long int end,int(*cmp)(void*, void*),void*(*filed)(void*),int reverse){
    if (start < end) {
        void* base = slice(self, start)->data; // 以要进行排序数组第0个元素为base
        int left = start;  // 左指针
        int right = end;   // 右指针

        while (left < right) {
            // 从右向左找,找到比base小的元素
            while (left < right && (cmp(filed(slice(self, right)->data), filed(base)) * reverse) >= 0) {
                right--;
            }
            // 比base小,替换left所在位置的元素
            slice(self, left)->data = slice(self, right)->data;

            // 从左向右找,找到比base大的元素
            while (left < right && (cmp(filed(slice(self, left)->data), filed(base)) * reverse) <= 0) {
                left++;
            }
            // 比base大,替换right所在位置的元素
            slice(self, right)->data = slice(self, left)->data;
        }
        slice(self, left)->data = base; // 将base放到正确的位置

        // 递归排序左右子数组
        _quickSort(self, start, left - 1, cmp,filed ,reverse);
        _quickSort(self, left + 1, end, cmp,filed, reverse);
    }
}
static void quickSort(myListOP *self,int(*cmp)(void*, void*),void*(*filed)(void*),int reverse){
    if (isNullOrEmpty(self))
    {
        return;
    }
    return _quickSort(self,0,self->length-1,cmp,filed,reverse);
}


static unsigned short int mysizeof(char * obj,unsigned short int size,unsigned int i){
    if (obj==0||size==0){return 0;}
    for (; size>1&&*(char*)(obj+size-1) - *(char*)(obj+size-2)==0; size--);//尾地址为obj+size-1
    return size;
}
static unsigned int pack(myListOP *self,char* buf,unsigned int length,unsigned short int max_size){
    return self->packVarLength(self,buf,length,(unsigned short int(*)(void*,unsigned short int ,unsigned int ))mysizeof,max_size);
}
unsigned int packVarLength(myListOP *self,char* buf,unsigned int length,unsigned short (*sizefun)(void* obj,unsigned short int max_size,unsigned int i),unsigned short int max_size){
    //将对象打包成字节流
    unsigned int used=0;
    void* obj=0;
    unsigned short int size=0;
    unsigned short int min_buf_len = sizeof(unsigned short int)*2;
    self->packed=0;
    if (self->pack_use_max_size)
    {
        min_buf_len =  sizeof(unsigned short int)*3;
    }
    if (length<min_buf_len)
    {
        return 0;
    }
    if (isNullOrEmpty(self))
    {
        return 0;
    }
    // 为总大小腾出空间
    used+=sizeof(unsigned short int);
    if (self->pack_use_max_size)
    {
        //如果启用最大大小,则为最大大小腾出空间
        used+=sizeof(unsigned short int);
    }
    //再循环写入每个元素
    while(obj=self->slice(self,self->__lastPacked++)){
        size = sizefun(obj,max_size,self->__lastPacked-1);
        if (self->pack_use_max_size)
        {
            max_size = max_size<size?size:max_size;
        }
        //需要写入的字节数为size+sizeof(unsigned short int)
        //如果写入量超过长度,则返回实际使用量;
        if (used+size+sizeof(unsigned short int)>length)
        {
            *(unsigned short int *)(buf) =used;
            if (self->pack_use_max_size)
            {
                *(unsigned short int *)(buf+sizeof(unsigned short int)) =max_size;
            }
            self->__lastPacked--;//回退计数器
            return used;//未打包完,返回使用量
        }
        //否则则写入大小和数据
        *(unsigned short int *)(buf+used) =size;
        used+=sizeof(unsigned short int);
        memcpy(buf+used,obj,size);
        used+=size;
    }
    self->__lastPacked = 0;//这里说明打包完了
    *(unsigned short int *)(buf) =used;
    if (self->pack_use_max_size)
    {
        *(unsigned short int *)(buf+sizeof(unsigned short int)) =max_size;
    }
    self->packed=1;
    return used;
}
myListOP* myListDUnpack(char pack_use_max_size,char* buf,void(*printData)(void*)){
    unsigned int total = *(unsigned short int *)buf;//协议包的总大小
    if (total<2*sizeof(unsigned short int)+1)//如果比最小的情况还小(一个总大小,一个对象,对象只写入了一个字节)
    {
        return 0;
    }
   
    unsigned int delta=sizeof(unsigned short int);//偏移量,头两个字节是协议包大小
    unsigned int num =0;//总元素数量
    unsigned int maxSize = *(unsigned short int *)(buf+delta);//最大元素的大小,假设第一个最大
    unsigned int currentSize=0;

    //找到要申请的地址的大小
    if (pack_use_max_size)
    {
        maxSize = *(unsigned short int *)(buf+sizeof(unsigned short int));
        delta+=sizeof(unsigned short int);
    }

    // 先获取最大的大小
    while (delta<total)//不会出现等于,最少会写入1字节的obj
    {
        num=num+1;
        currentSize = *(unsigned short int *)(buf+delta);
        if (maxSize<currentSize)
        {
            maxSize = currentSize;
        }
        delta+=currentSize+sizeof(unsigned short int);
    }
    
    delta = sizeof(unsigned short int);
    if (pack_use_max_size)
    {
        delta+=sizeof(unsigned short int);
    }

    //再申请内存
    myListOP* arr = myListDInit(printData);if (arr == 0){return 0;}
    arr->pack_use_max_size=pack_use_max_size;//继承原有的格式
    while (delta<total)//不会出现等于,最少会写入1字节的obj
    {
        void* obj=malloc(maxSize);if (obj == 0){return 0;}
        currentSize = *(unsigned short int *)(buf+delta);
        delta+=sizeof(unsigned short int);
        memset(obj,*(char*)(buf+delta+currentSize-1),maxSize);//以最后一个字节初始化
        memcpy(obj,buf+delta,currentSize);
        delta+=currentSize;
        arr->append(arr,obj);//对链表,存的是对象的地址
    }
    return arr; 
}
static myListOP* unpack(myListOP* self,char* buf,void(*printData)(void*)){
    //兼容层
    return myListDUnpack(self->pack_use_max_size,buf,printData);
}
static int delByAddrNoFree(myListOP *self,void* obj,unsigned int times){
    if (self==0||self->isNullOrEmpty(self)||obj==0)
    {
        return 0;
    }
    do
    {
        unsigned int where = self->find(self,obj,times);
        if (where == -1)
        {
            break;
        }
        self->delNoFree(self,where);
    } while (times--);
    return times;    
}

static int delByAddr(myListOP *self,void* obj,unsigned int times){
    if (self==0||self->isNullOrEmpty(self)||obj==0)
    {
        return 0;
    }
    do
    {
        unsigned int where = self->find(self,obj,times);
        if (where == -1)
        {
            break;
        }
        self->del(self,where);
    } while (times--);
    return times;    
}

static int add(myListOP *self,myListOP *other){
    void* obj =0;
    unsigned int i =0;
    while (obj=other->slice(other,i++))
    {
        self->append(self,obj);
    }
}

static int sub(myListOP *self,myListOP *other){
    int ret =0;
    if (self ==0||other ==0) 
    {
        return ret;
    }
    if (self->isNullOrEmpty(self)||other->isNullOrEmpty(other))
    {
        return ret;
    }
    void* obj_self =0;
    void* obj_other=0;
    unsigned int i =0;
    unsigned int j=0;
    
    while (obj_other=other->slice(other,i++))
    {
        while (obj_self=self->slice(self,j++))
        {
            if (obj_other==obj_self)
            {
                self->delByAddr(self,obj_self,0);
            }
        }
    }
}
myListOP* myListDInit(void(*printData)(void*)){
    myListOP *self = (myListOP *) malloc(sizeof(myListOP));
    if (self ==0)
    {
        return 0;
    }
    bzero(self,sizeof(myListOP));
    //申请头节点
    self->data = (myListP) malloc(sizeof(myList));
    if (self->data ==0)
    {
        return 0;
    }
    self->data->data=0;
    self->data->next=self->data;
    self->data->prev=self->data;
    self->append=append;
    self->del=delAll;
    self->delNoFree = del;
    self->__str=printData;
    self->destory=destory;
    self->find=find;
    self->findby=findby;
    self->insert=insert;
    self->isNullOrEmpty=isNullOrEmpty;
    self->length=0;
    self->slice=_slice;
    self->_slice=slice;
    self->unic=unic;
    self->print=print;
    self->dequeue=dequeue;
    self->pop=pop;
    self->push=(int (*)(struct myListOP*,void* data))append;
    self->queue=(int (*)(struct myListOP*,void* data))append;
    self->quickSort=quickSort;
    self->_quickSort=_quickSort;
    self->destoryNoFree=destoryNoFree;
    self->unicNoFree=unicNoFree;
    self->packVarLength=packVarLength;
    self->pack=pack;
    self->unpack=unpack;
    self->delByAddr = delByAddr;

    return self;
}
    
复制代码
doublyList.h
c 复制代码
#ifndef  __MYDOUBLYLIST_STRUCT__
#define __MYDOUBLYLIST_STRUCT__

/* 双向循环链表,涵盖操作类
*  
* 用法: 需要外部创建结构体或对象,同时准备好该结构体或对象的打印(print)方法
* 请注意:长度从0开始,到length结束
* 推荐以以下方式迭代链表
* while(obj=.slice(,i++))
* 以下划线(_)开头的方法为某一方法的补充,或是低级实现,理想情况下不应当被使用
* 以下划线(__)开头的字段为内部实现依赖的字段,不应当被外界改变
* 在数组的实现中,部分方法依赖于长度(.length),其长度不应当被改变
* 以下操作是合法的
* _slice(0),_slice(length),_slice(-1),_slice(length+1)返回值分别为头数据,尾数据,0,0
* slice(1),slice(length),返回值分别为头尾节点内存的对象.
* 同一个链表操作类操作不同的链表 即op1->fun(op2,agrs) 该结果应该与 op2->fun(op2,agrs) 一致,但无法保证跨链表操作类结果一致

* 如需排序/去重/按字段查找,则需准备字段的方法
* 如需排序,需要提供比较方法
* 
* 初始 myListOP* mylistOP =  myListDInit((void(*)(void*))printData);
* 2025/5/9  修改返回void* 的slice可能段错误的问题
* 2025/5/10 修补编译器提示,增加unicNoFree,增加pack与unpack
* 2025/5/11 补充测试函数,放弃对单向链表的支持,重命名新增NoFree函数
*/
typedef struct myList{

 void * data;
 struct myList * prev;
 struct myList * next;
}myList,* myListP;

typedef struct myListOP{
 myListP data;
 //判断链是否为空,空返回1,非空返回0
 int (*isNullOrEmpty)(struct myListOP*);
 //将obj存放入链表的尾部,成功返回1,失败返回0
 int (*append)(struct myListOP*,void* data);
 /*
 删除链表上的第where个节点,会自动free该节点指向的对象
 returnVal: 0失败,1成功
 */
 int (*del)(struct myListOP*,unsigned int where);
 /*
 删除链表上的第where个节点,会自动free该节点指向的对象
 returnVal: 该节点指向的对象的地址
 */
 void* (*delNoFree)(struct myListOP*,unsigned int where);
 /*
 在where处插入obj对象
 returnVal: 0失败,1成功
 */
 int (*insert)(struct myListOP*,unsigned int where,void* obj);
 /*
 查找该对象times+1次,返回times+1次所对应的下标,times为0表示取第一个
 returnVal: where,-1表示未找到该对象
 */
 unsigned int (*find)(struct myListOP*self,void* obj,unsigned int times);
 /*
 在链表上保证链表上某个对象最多不出现time+1次,会free对象
 field:取字段函数,接受链表内存储的对象,返回要排序的字段的地址
 size:该字段的大小
 具体调用:memcmp(field(slice(self,i)->data),field(slice(self,j)->data),size)==0
 returnVal:删除了几个对象
 */
 unsigned int (*unic)(struct myListOP*self,void*(*field)(void*),long unsigned int size,unsigned int times);
     /*
 在链表上保证链表上某个对象最多不出现time+1次,不会free对象
 field:取字段函数,接受链表内存储的对象,返回要排序的字段的地址
 size:该字段的大小
 具体调用:memcmp(field(slice(self,i)->data),field(slice(self,j)->data),size)==0
 returnVal:删除了几个对象
 */
 unsigned int (*unicNoFree)(struct myListOP*self,void*(*field)(void*),long unsigned int size,unsigned int times);
 /* 
 返回链表内第i个链的地址,不应当被外部调用
 */
 myList* (*_slice)(struct myListOP* self,unsigned int i);
 /* 
 返回链表内第i个对象的地址
 应该被这么用:
 while(obj=op->slice(op,i++)){
 do something to op
 }
 */
 void* (*slice)(struct myListOP* self,unsigned int i);
 // 销毁链表,并且销毁链表内的所有对象(free obj)
 void (*destory)(struct myListOP *self);
 // 将链表内的所有对象挨个传给.__str方法,.__str方法应当在初始化时被正确设置为接受对象的地址并进行输出
 void (*print)(struct myListOP * self);
 /*
 field:取字段函数,接受链表内存储的对象,返回要排序的字段的地址
 cmp: 比较函数,接收target,接受由field产生的字段的地址,返回两个值的差值(cmp(filed(p->data),target))
 target:要比较的值的地址
 times:找第times+1个
 returnVal:找到返回where,没找到返回-1
 */
 unsigned int (*findby)(struct myListOP*self,int(*cmp)(void*,void*),void*(*field)(void*),void*target,unsigned int times);
 //.print会调用这个方法输出链表内的对象(会将每一个对象的地址输入进这个方法)
 void (*__str)(void*);
 //删除链表的第一个节点,将其内部存放的对象的地址返回(而不是free)
 void*  (*dequeue)(struct myListOP* self);
 //删除链表的尾节点,将其内部存放的对象的地址返回(而不是free)
 void*  (*pop)(struct myListOP* self);
 //将obj存放入链表的尾部,成功返回1,失败返回0
 int  (*push)(struct myListOP*,void* obj);
 //将obj存放入链表的尾部,成功返回1,失败返回0
 int  (*queue)(struct myListOP*,void* data);
 //对链表的一部分进行快速排序
 void (*_quickSort)(struct myListOP*self,long int start,long int end,int(*cmp)(void*, void*),void*(*filed)(void*),int reverse);
 //对整个链表快速排序,field:根据对象的哪个字段地址进行排序,cmp接受两个字段的地址,返回两个字段值的差值,reverse为正则正序,为负则倒叙,0不排序
 void (*quickSort)(struct myListOP *self,int(*cmp)(void*, void*),void*(*filed)(void*),int reverse);
 //删除整个链表,但不释放链表中的对象
 void (*destoryNoFree)(struct myListOP*self);
 //按地址删除某一元素,obj要删除的对象,times删除次数,返回实际删除了几次,不释放obj
 int (*delByAddr)(struct myListOP *self,void* obj,unsigned int times);
 /*
 将对象打包成字节流,写入到buf,会删除重复的尾字节
 字节流格式:unsigened short int used(2字节) unsigened short int datalen(2字节) data
 如果.pack_use_max_size != 0,则在used 之后写入该对象的最大大小
 buf:缓冲区,字节流写入的地址
 length:缓冲区buf的长度
 max_size:链表上存储的obj最大的大小(如大小不一致,请使用.packVarLength)
 returnVal:往缓冲区实际写入的字节数
 */
 unsigned int (*pack)(struct myListOP *self,char* buf,unsigned int length,unsigned short int max_size);
 /*
 将对象打包成字节流,写入到buf,会删除重复的尾字节
 字节流格式:unsigened short int used(2字节)unsigened short int datalen(2字节) data
 如果.pack_use_max_size != 0,则在used 之后写入该对象的最大大小
 buf:缓冲区,字节流写入的地址
 length:缓冲区buf的长度
 size:取size函数,传入obj对象,返回这个对象占用了多少个字节,obj list里存放的对象,max_size:这个对象理应占的最大字节数,i,第i个对象
 如果size函数返回了一个比max_size更大的数,那么以size返回的数据的最大值作为max_size被写入
 returnVal:往缓冲区实际写入的字节数
 */
 unsigned int (*packVarLength)(struct myListOP *self,char* buf,unsigned int length,unsigned short (*size)(void* obj,unsigned short int max_size,unsigned int i),unsigned short int max_size);
 /*
 将字节流解包成对象,会写入尾部的重复字节
 字节流格式:unsigened short int used(2字节)unsigened short int datalen(2字节) data
 如果.pack_use_max_size != 0,使用used之后的2字节作为最大长度进行创建内存
 buf:缓冲区,字节流读取的地址
 printData:返回操作类初始化时需要的printData
 returnVal:操作类
 */
 struct myListOP* (*unpack)(struct myListOP* self,char* buf,void(*printData)(void*));
 unsigned int length;//链表的长度
 unsigned int __index;//内部变量,加速slice与_slice的返回
 unsigned int __lastPacked;//内部变量,记录上次打包的位置
 char pack_use_max_size;//是否使用最大的元素大小,修改打包的格式
 char packed;//是否打包完毕
 myListP __last;//内部变量,加速slice与_slice的返回
 myListP __head;//内部变量,加速slice与_slice的返回

} myListOP;
//初始化函数
myListOP* myListDInit(void(*printData)(void*));
/*
将字节流解包成对象,会写入尾部的重复字节
字节流格式:unsigened short int used(2字节)unsigened short int datalen(2字节) data
如果pack_use_max_size != 0,使用used之后的2字节作为最大长度进行创建内存
buf:缓冲区,字节流读取的地址
printData:返回操作类初始化时需要的printData
returnVal:操作类
*/
myListOP* myListDUnpack(char pack_use_max_size,char* buf,void(*printData)(void*));
#endif
复制代码
array.c
c 复制代码
 // 实现list的头插,尾插,头删,尾删,任意位置删除,任意位置添加
#include <stdio.h>
#include <string.h>
#include "array.h"
static int isNull(myArrayOP* self){
 if (self ==0 || self->data ==0){return 1;}
 return 0;
}
static int isNullOrEmpty(myArrayOP* self){
 if (isNull(self) || self->length ==0)
 {
     return 1;
 }
 return 0;
 
}
static void* slice(myArrayOP* self,unsigned int i){
 if (i>= self->length || i<0)
 {
     return 0;
 }
 
 return self->data+self->size*i;
}
static int del(myArrayOP* self,unsigned int where){
 if (isNullOrEmpty(self))
 {
     return 0;
 }//判断是否非空
 void* data = self->data;
 if (where > self->length || where <0)
 {
     return 0;
 }
 if (self->length == where+1)//如果最后一个,则直接移动length,避免越界
 {
     self->length = self->length-1;
     return 0;
 }
 
 for (unsigned int i = where; i < self->length; i++)
 {
     // data->data[i] = data->data[i+1];
     memcpy(data+self->size*i,data+self->size*(i+1),self->size);
 }
 self->length = self->length-1;
 return 0;
 
}
static void* delNoFree (myArrayOP* self,unsigned int where){
 if (isNullOrEmpty(self))
 {
     return 0;
 }//判断是否非空
 void* ret = malloc(self->size);
 memcpy(ret,self->slice(self,where),self->size);
 del(self,where);
 return ret;
}
static int insert(myArrayOP* self,unsigned int where,void* obj){
 if (isNull(self))
 {
     return 0;
 }//判断是否非空
 void* data = self->data;
 if (self->length == self->max_length)
 {
     return 0;
 }
 if (where > self->length||where<0)
 {
     return 0;
 }
 
 if (self->length ==0)
 {
     // data->data[0] = obj;
     memcpy(data,obj,self->size);
     self->length++;
     return 1;
 } 
 
 for (unsigned int i =self->length ; i > where; i--)
 {
     memcpy(data+self->size*i,data+self->size*(i-1),self->size);
 }
 self->length = self->length+1;
 memcpy(data+where*self->size,obj,self->size);
 
 return 1;
}

static int insertHead(myArrayOP* self,void* num){
 return insert(self,0,num);
}
static int insertTail(myArrayOP* self,void* num){
 if (isNull(self))
 {
     return 0;
 }//判断是否非空
 return insert(self,self->length,num);

}
static int delHead (myArrayOP* self){
 return del(self,0);
}
static int delTail (myArrayOP* self){
 return del(self,self->length);
}
static void* delHeadNoFree (myArrayOP* self){
 return delNoFree(self,0);
}
static void* delTailNoFree (myArrayOP* self){
 return delNoFree(self,self->length-1);
}
static unsigned int find(struct myArrayOP*self,void* obj,unsigned int times){
 void* p =0;
 unsigned int count =0;
 for (unsigned int i = 0; i < -1; i++)
 {
     p=slice(self,i);
     if (p==0)
     {
         break;
     }
     if (p==obj)
     {
         if (times == count)
         {
             return i;
         }
         count ++;
     }

 }
 return -1;
}
static unsigned int findby(struct myArrayOP*self,int(*cmp)(void*,void*),void*(*filed)(void*),void*target,unsigned int times){//cmp应该返回是否是要找的值
 void* p =0;
 unsigned int count =0;
 for (unsigned int i = 0; i < -1; i++)
 {
     p=self->slice(self,i);
     if (p==0)
     {
         break;
     }
     if (cmp(filed(p),target)==0)
     {
         if (times == count)
         {
             return i;
         }
         count ++;
     }
 }
 return -1;
}
static unsigned int _index(myArrayOP* self,void* obj){
 return find(self, obj,0);
}

static unsigned int unic (struct myArrayOP*self,void*(*field)(void*),unsigned int times){
 unsigned int count=0;
 unsigned int ret =0;
 for (unsigned int i = 1; i < self->length; i++)
 {
     count =0;
     for (unsigned int j = i+1; j < self->length; j++)
     {
         if (memcmp(field(self->slice(self,i)),field(self->slice(self,j)),self->size)==0)
         {
             if (count >= times)
             {
                 self->del(self,j);
                 j=j-1;
             }
             count=count+1;
             ret = ret+1;
         }
     }
 }
 return ret;
}
static void print(myArrayOP * self){
 void* obj;
 unsigned int i=0;
 if (isNullOrEmpty(self))
 {
     return;
 }
 while (obj=self->slice(self,i++))
 {
     self->__str(obj);
 }
 printf("\n");
 return;
}
static void destory(myArrayOP *self){
 if (self ==0)
 {
     return;
 }
 if (self->data ==0)
 {
     return;
 }
 free (self->data);
 self->data=0;
 free(self);
}

static void _quickSort(myArrayOP *self,long int start,long int end,int(*cmp)(void*, void*),void*(*filed)(void*),int reverse){
 if (start < end) {
     void* base = malloc(self->size);
     memcpy(base,slice(self, start),self->size);// 以要进行排序数组第0个元素为base
     int left = start;  // 左指针
     int right = end;   // 右指针

     while (left < right) {
         // 从右向左找,找到比base小的元素
         while (left < right && (cmp(filed(slice(self, right)), filed(base)) * reverse) >= 0) {
             right--;
         }
         memcpy(slice(self, left),slice(self, right),self->size);
         while (left < right && (cmp(filed(slice(self, left)), filed(base)) * reverse) <= 0) {
             left++;
         }
         memcpy(slice(self, right),slice(self, left),self->size);
     }
     // slice(self, left)->data = base; // 将base放到正确的位置
     memcpy(slice(self, left),base,self->size);
     free(base);
     // 递归排序左右子数组
     _quickSort(self, start, left - 1, cmp,filed, reverse);
     _quickSort(self, left + 1, end, cmp,filed, reverse);
 }
}
static void quickSort(myArrayOP *self,int(*cmp)(void*, void*),void*(*filed)(void*),int reverse){
 if (isNullOrEmpty(self))
 {
     return;
 }
 return _quickSort(self,0,self->length-1,cmp,filed,reverse);
}
static unsigned short int mysizeof(char * obj,unsigned int size){
 if (obj==0||size==0){return 0;}
 for (; size>1&&*(char*)(obj+size-1) - *(char*)(obj+size-2)==0; size--);//尾地址为obj+size-1
 return size;
}
static unsigned int pack(myArrayOP *self,char* buf,unsigned int length){
 //将对象打包成字节流
 //格式:unsigened short int used(2字节)unsigened short int len(2字节)data
 //如果定义了宏 __PACK_WRITE_MAXSIZE__,则在used后写入max_size 
 unsigned int used=0;
 void* obj=0;
 unsigned short int size=0;
 unsigned int min_buf_len = sizeof(unsigned short int)*2;
 self->packed=0;
 if (self->pack_use_max_size)
 {
     min_buf_len =  sizeof(unsigned short int)*3;
 }
 if (length<min_buf_len)
 {
     return 0;
 }
 if (isNullOrEmpty(self))
 {
     return 0;
 }
 // 为总大小腾出空间
 used+=sizeof(unsigned short int);

 
 if (self->pack_use_max_size)
 {
     *(unsigned short int *)(buf+used) =self->size;
     used+=sizeof(unsigned short int);
 }
 //再循环写入每个元素
 while(obj=self->slice(self,self->__lastPacked++)){
     size = mysizeof(obj,self->size);
     //需要写入的字节数为size+sizeof(unsigned short int)
     //如果写入量超过长度,则返回实际使用量;
     if (used+size+sizeof(unsigned short int)>length)
     {
             *(unsigned short int *)(buf) =used;
             self->__lastPacked--;//回退计数器
             return used;//未打包完,返回使用量
     }
     //否则则写入大小和数据
     *(unsigned short int *)(buf+used) =size;
     used+=sizeof(unsigned short int);
     memcpy(buf+used,obj,size);
     used+=size;
 }
 self->__lastPacked = 0;//这里说明打包完了
 self->packed=1;
 *(unsigned short int *)(buf) =used;
 return used;
}
myArrayOP* myArrayUnpack(char pack_use_max_size,char* buf,void(*printData)(void*)){
 unsigned int total = *(unsigned short int *)buf;//协议包的总大小
 if (total<2*sizeof(unsigned short int)+1)//如果比最小的情况还小(一个总大小,一个对象,对象只写入了一个字节)
 {
     return 0;
 }
 
 //先循环遍历,找到最大的元素大小和要申请的地址的大小
 unsigned int delta=sizeof(unsigned short int);//偏移量,头两个字节是协议包大小
 unsigned int num =0;//总元素数量
 unsigned int maxSize = *(unsigned short int *)(buf+delta);//最大元素的大小,假设第一个最大
 unsigned int currentSize=0;
 if (pack_use_max_size)
 {
     // 如果有写max_size 则使用
     maxSize = *(unsigned short int *)(buf+sizeof(unsigned short int));
     delta+=sizeof(unsigned short int);
 }
 
     while (delta<total)//不会出现等于,最少会写入1字节的obj
 {
     num=num+1;
     currentSize = *(unsigned short int *)(buf+delta);
     if (maxSize<currentSize)
     {
         maxSize = currentSize;
     }
     delta+=currentSize+sizeof(unsigned short int);
 }
 
 delta = sizeof(unsigned short int);
 //再申请内存
 myArrayOP* arr = myArrayInit(maxSize*num,maxSize,printData);if (arr == 0){return 0;}
 //为了方便还原数据,申请maxSize大小的内存;
 void* obj=malloc(maxSize);if (obj == 0){return 0;}

 while (delta<total)//不会出现等于,最少会写入1字节的obj
 {
     currentSize = *(unsigned short int *)(buf+delta);
     delta+=sizeof(unsigned short int);
     memset(obj,*(char*)(buf+delta+currentSize-1),maxSize);//以最后一个字节初始化
     memcpy(obj,buf+delta,currentSize);
     delta+=currentSize;
     arr->append(arr,obj);
 }
 free(obj);
 arr->pack_use_max_size=pack_use_max_size;//继承原有的格式
 return arr; 
}
static myArrayOP* unpack(myArrayOP* self,char* buf,void(*printData)(void*)){
 //兼容层
 return myArrayUnpack(self->pack_use_max_size,buf,printData);
}
static int delByAddr(myArrayOP *self,void* obj){
 if (self==0)
 {
     return -1;
 }
 if (isNullOrEmpty(self))
 {
     return -1;
 }
 if (obj<self->data||obj>(self->data+self->length*self->size))
 {
     return -1;
 }
 unsigned int where = (unsigned int)((char*)obj - (char*)self->data)/self->size;
 self->del(self,where);
 return where;
}
static int add(myArrayOP *self,myArrayOP *other){
 void* obj =0;
 unsigned int i =0;
 while (obj=other->slice(other,i++))
 {
     self->append(self,obj);
 }
}
static int sub(myArrayOP *self,myArrayOP *other){
 int ret =0;
 if (self ==0||other ==0) 
 {
     return ret;
 }
 if (self->isNullOrEmpty(self)||other->isNullOrEmpty(other))
 {
     return ret;
 }
 if (self->size!=other->size) //两个数组中数据大小不一样,不比较
 {
     ret = -1;
     return ret;
 }
 unsigned int size = self->size;
 
 
 void* obj_self =0;
 void* obj_other=0;
 unsigned int i =0;
 unsigned int j=0;
 
 while (obj_other=other->slice(other,i++))
 {
     while (obj_self=self->slice(self,j++))
     {
         if (memcmp(obj_self,obj_other,size)==0)
         {
             self->delByAddr(self,obj_self);
         }
     }
 }
}

static myArrayOP* copy(myArrayOP* self){
 myArrayOP* ret = myArrayInit(self->max_length,self->size,self->__str);
 memcpy(ret->data,self->data,self->size*self->length);
 return  ret;
}
static myArrayOP* setter(myArrayOP* self,myArrayOP*other){
 memcpy(self->data,other->data,self->size*self->length);
 return  self;
}
myArrayOP* myArrayInit(unsigned int max_length,unsigned int size,void(*printData)(void*)){
 myArrayOP * self = 0;
 self = (myArrayOP*) malloc(sizeof(myArrayOP));
 bzero(self,sizeof(myArrayOP));

 self->data = calloc(max_length,size);
 // malloc(sizeof(myList));
 bzero(self->data,sizeof(max_length*size));
 self->max_length=max_length;
 self->size=size;
 self->__str=printData;
 self->del = del;
 self->delHead=delHead;
 self->delTail=delTail;
 self->delNoFree=delNoFree;
 self->find=find;
 self->index=_index;
 self->insert=insert;
 self->inserTail=insertTail;
 self->insertHead=insertHead;
 self->isNullOrEmpty=isNullOrEmpty; 
 self->slice=slice;
 self->unic=unic;
 self->print=print;
 self->destory=destory;
 self->delHeadNoFree=delHeadNoFree;
 self->delTailNoFree=delTailNoFree;
 self->delNoFree=delNoFree;
 self->quickSort=quickSort;
 self->_quickSort=_quickSort;
 self->append=insertTail;
 self->push=insertTail;
 self->queue=insertTail;
 self->dequeue=delHeadNoFree;
 self->pop=delTailNoFree;
 self->findby=findby;
 self->pack=pack;
 self->unpack=unpack;
 self->copy=copy;
 self->setter = setter;
 return self;
}
复制代码
array.h
c 复制代码
 #ifndef  __MYARRAYLIST_STRUCT__
#define __MYARRAYLIST_STRUCT__
#include <stdlib.h>
// 数组,堆上的对象数组
// 用法: 需要外部创建结构体或对象,同时准备好该结构体或对象的打印(print)方法
// 请注意:长度从0开始,到length结束
// 推荐以以下方式迭代链表
// while(obj=.slice(,i++))
// 以下划线(_)开头的方法为某一方法的补充,或是低级实现,理想情况下不应当被使用
// 以下划线(__)开头的字段为内部实现依赖的字段,不应当被外界改变
// 在数组的实现中,部分方法依赖于长度(.length),其长度不应当被改变
// 以下操作是合法的
// _slice(0),_slice(length),_slice(-1),_slice(length+1)返回值分别为头数据,尾数据,0,0
// slice(1),slice(length),返回值分别为头尾节点内存的对象.
// 同一个链表操作类操作不同的链表 即op1->fun(op2,agrs) 该结果应该与 op2->fun(op2,agrs) 一致,但无法保证跨链表操作类结果一致

/* 封装测试于2025/4/30,修复部分.length操作
*  
* 2025/4/16 添加类
* 2025/4/16 添加通用的测试方法
* 2025/4/25 添加_destory方法,未测试,理应是好的
* 2025/4/27 修复findby与quickSort,_quickSort,findby的cmp函数,使其统一,并新增字段field函数,应当返回一对象内部的地址
* 2025/4/27 针对有头单项链表测试,修改有头单项链表,定义1-.length为合法操作
* 2025/5/9  修补数组,使其对任意的obj有效,重命名新增NoFree函数
* 2025/5/10 新增pack和unpack方法,打包/解包成数据流
*/
typedef struct myArrayOP{
 void* data;  //堆上的数组
 size_t length; //目前的长度,0为空
 size_t max_length;//数组的最大长度
 unsigned int __lastPacked;
 char pack_use_max_size;//是否使用最大的元素大小
 char packed;
 void (*__str)(void*);//打印方法
 unsigned short int size;//内部每个元素的大小
 int (*isNullOrEmpty)(struct myArrayOP*);//判断列表是否为空
 int (*insertHead)(struct myArrayOP*,void* obj);//在数组的头插入
 int (*inserTail)(struct myArrayOP*,void* obj);//在数组的末尾插入
 int (*delHead)(struct myArrayOP*);//删除数组的头
 int (*delTail)(struct myArrayOP*);//删除数组的尾
 void* (*delHeadNoFree)(struct myArrayOP*);//删除数组的头(不会自动调用free),会copy一份返回
 void* (*delTailNoFree)(struct myArrayOP*);//删除数组的尾(不会自动调用free),会copy一份返回
 int (*del)(struct myArrayOP*,unsigned int where);//在数组的where处删除某个对象(会自动调用free)
 void* (*delNoFree)(struct myArrayOP*,unsigned int where);//在数组的where处删除某个对象(不会自动调用free),会copy一份返回
 int (*insert)(struct myArrayOP*,unsigned int where,void* obj);//在数组的where处插入对象
 unsigned int (*index)(struct myArrayOP*,void* obj);//取该对象的数组下标
 unsigned int (*find)(struct myArrayOP*,void* obj,unsigned int times);//查找该对象times+1次,返回times+1次所对应的下标,times为0表示取第一个
 unsigned int (*findby)(struct myArrayOP*self,int(*cmp)(void*,void*),void*(*filed)(void*),void*target,unsigned int times);//使用cmp查找该对象的filed字段对应的target,times+1次,返回times+1次所对应的下标,times为0表示取第一个
 unsigned int (*unic) (struct myArrayOP*self,void*(*field)(void*),unsigned int times);//在数组上保证数组上某个对象最多不出现time+1次,filed函数应当返回特征字段的地址,size应当设置为特征的大小
 void* (*slice)(struct myArrayOP* self,unsigned int i);//切片函数,数组上的第i个对象
 void (*destory)(struct myArrayOP *self);//销毁数组,会释放所有的该数组上的对象
 // void (*destoryNoFree)(struct myArrayOP *self);
 void (*print)(struct myArrayOP * self);//使用.__str方法打印数组上的所有对象
 void (*_quickSort)(struct myArrayOP *self,long int start,long int end,int(*cmp)(void*, void*),void*(*filed)(void*),int reverse);//从start到end的快速排序
 void (*quickSort)(struct myArrayOP *self,int(*cmp)(void*, void*),void*(*filed)(void*),int reverse);//整个链表的快速排序,cmp方法返回给出的两个对象哪个更大,reverse为正则正序,为负则逆序,0不做排序
 int (*append)(struct myArrayOP*,void* data);//尾插
 void*  (*dequeue)(struct myArrayOP* self);//在数组上将第0个元素删除,将元素拷贝一份到新的堆空间并返回拷贝后的地址,需要手动free
 void*  (*pop)(struct myArrayOP* self);//在数组上将最后一个元素删除,将元素拷贝一份到新的堆空间并返回拷贝后的地址,需要手动free
 int  (*push)(struct myArrayOP*,void* data);//拷贝该元素到数组的最后一位
 int  (*queue)(struct myArrayOP*,void* data);//拷贝该元素到数组的最后一位
 unsigned int (*pack)(struct myArrayOP *self,char* buf,unsigned int length);//将其内部的数据打包成字节流
 struct myArrayOP* (*unpack)(struct myArrayOP *self,char* buf,void(*printData)(void*));//将字节流解包成内部数据,返回一个新的对象
 int (*delByAddr)(struct myArrayOP *self,void* obj);//按地址删除某一元素
 struct myArrayOP *(*copy)(struct myArrayOP *self);//拷贝副本
 struct myArrayOP *(*setter)(struct myArrayOP *self,struct myArrayOP *other);//将other的数据域拷贝至self的数据域
} myArrayOP;
//初始化函数
myArrayOP* myArrayInit(unsigned int max_length,unsigned int size,void(*print)(void*));
/*
将字节流解包成对象,会写入尾部的重复字节
字节流格式:unsigened short int used(2字节)unsigened short int datalen(2字节) data
如果pack_use_max_size != 0,使用used之后的2字节作为最大长度进行创建内存
buf:缓冲区,字节流读取的地址
printData:返回操作类初始化时需要的printData
returnVal:操作类
*/
myArrayOP* myArrayUnpack(char pack_use_max_size,char* buf,void(*printData)(void*));
#endif
相关推荐
仍然探索未知中3 分钟前
Linux守护进程
linux·运维·服务器
馨羽的玩具1 小时前
查哪个程序一直登录sql server失败
运维·服务器·数据库
luoqice1 小时前
在嵌入式 Linux 系统中,配置 DNS 以实现内网或外网连接
linux·运维·服务器
妙妙屋(zy)2 小时前
基于Astro开发的Fuwari静态博客模版配置CICD流程
服务器·docker
IvanCodes2 小时前
三、Linux用户与权限管理详解
linux·运维·服务器
默默敲代码的徐哥儿2 小时前
八股文整理——计算机网络
服务器·网络·计算机网络
cyber_两只龙宝3 小时前
RHCE综合项目:分布式LNMP私有博客服务部署
linux·运维·服务器·分布式·虚拟机·dns·nfs
字节高级特工3 小时前
【Linux篇】补充:消息队列和systemV信号量
linux·运维·服务器·c语言·数据库
wanhengidc4 小时前
服务器分布式的作用都有什么?
运维·服务器·分布式
Arvin6275 小时前
Linux 完整删除 Systemd 服务的步骤
linux·服务器