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