马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
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;
- }
-
复制代码- #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
复制代码- // 实现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;
- }
复制代码- #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
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |