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

发布于:2025-05-21 ⋅ 阅读:(18) ⋅ 点赞:(0)

server.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

#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

#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
#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
 // 实现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
 #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

网站公告

今日签到

点亮在社区的每一天
去签到