使用C语言实现vector动态数组的实例分享
下面是做项目时实现的一个动态数组,先后加入了好几个之后的项目,下面晒下代码。
头文件:
#ifndef__CVECTOR_H__ #define__CVECTOR_H__ #defineMIN_LEN256 #defineCVEFAILED-1 #defineCVESUCCESS0 #defineCVEPUSHBACK1 #defineCVEPOPBACK2 #defineCVEINSERT3 #defineCVERM4 #defineEXPANED_VAL1 #defineREDUSED_VAL2 typedefvoid*citerator; typedefstruct_cvector*cvector; #ifdef_cplusplus #defineEXTERN_extern"C" #else #defineEXTERN_extern #endif EXTERN_cvectorcvector_create(constsize_tsize); EXTERN_voidcvector_destroy(constcvectorcv); EXTERN_size_tcvector_length(constcvectorcv); EXTERN_intcvector_pushback(constcvectorcv,void*memb); EXTERN_intcvector_popback(constcvectorcv,void*memb); EXTERN_size_tcvector_iter_at(constcvectorcv,citeratoriter); EXTERN_intcvector_iter_val(constcvectorcv,citeratoriter,void*memb); EXTERN_citeratorcvector_begin(constcvectorcv); EXTERN_citeratorcvector_end(constcvectorcv); EXTERN_citeratorcvector_next(constcvectorcv,citeratoriter); EXTERN_intcvector_val_at(constcvectorcv,size_tindex,void*memb); EXTERN_intcvector_insert(constcvectorcv,citeratoriter,void*memb); EXTERN_intcvector_insert_at(constcvectorcv,size_tindex,void*memb); EXTERN_intcvector_rm(constcvectorcv,citeratoriter); EXTERN_intcvector_rm_at(constcvectorcv,size_tindex); /*fortest*/ EXTERN_voidcv_info(constcvectorcv); EXTERN_voidcv_print(constcvectorcv); #endif/*EOFfilecvector.h*/
C文件:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #defineMIN_LEN256 #defineCVEFAILED-1 #defineCVESUCCESS0 #defineCVEPUSHBACK1 #defineCVEPOPBACK2 #defineCVEINSERT3 #defineCVERM4 #defineEXPANED_VAL1 #defineREDUSED_VAL2 typedefvoid*citerator; typedefstruct_cvector { void*cv_pdata; size_tcv_len,cv_tot_len,cv_size; }*cvector; #defineCWARNING_ITER(cv,iter,file,func,line)\ do{\ if((cvector_begin(cv)>iter)||(cvector_end(cv)<=iter)){\ fprintf(stderr,"var("#iter")warngoutofrange,"\ "atfile:%sfunc:%sline:%d!!/n",file,func,line);\ returnCVEFAILED;\ }\ }while(0) #ifdef_cplusplus #defineEXTERN_extern"C" #else #defineEXTERN_extern #endif EXTERN_cvectorcvector_create(constsize_tsize); EXTERN_voidcvector_destroy(constcvectorcv); EXTERN_size_tcvector_length(constcvectorcv); EXTERN_intcvector_pushback(constcvectorcv,void*memb); EXTERN_intcvector_popback(constcvectorcv,void*memb); EXTERN_size_tcvector_iter_at(constcvectorcv,citeratoriter); EXTERN_intcvector_iter_val(constcvectorcv,citeratoriter,void*memb); EXTERN_citeratorcvector_begin(constcvectorcv); EXTERN_citeratorcvector_end(constcvectorcv); EXTERN_citeratorcvector_next(constcvectorcv,citeratoriter); EXTERN_intcvector_val_at(constcvectorcv,size_tindex,void*memb); EXTERN_intcvector_insert(constcvectorcv,citeratoriter,void*memb); EXTERN_intcvector_insert_at(constcvectorcv,size_tindex,void*memb); EXTERN_intcvector_rm(constcvectorcv,citeratoriter); EXTERN_intcvector_rm_at(constcvectorcv,size_tindex); /*fortest*/ EXTERN_voidcv_info(constcvectorcv); EXTERN_voidcv_print(constcvectorcv); cvectorcvector_create(constsize_tsize) { cvectorcv=(cvector)malloc(sizeof(struct_cvector)); if(!cv)returnNULL; cv->cv_pdata=malloc(MIN_LEN*size); if(!cv->cv_pdata) { free(cv); returnNULL; } cv->cv_size=size; cv->cv_tot_len=MIN_LEN; cv->cv_len=0; returncv; } voidcvector_destroy(constcvectorcv) { free(cv->cv_pdata); free(cv); return; } size_tcvector_length(constcvectorcv) { returncv->cv_len; } intcvector_pushback(constcvectorcv,void*memb) { if(cv->cv_len>=cv->cv_tot_len) { void*pd_sav=cv->cv_pdata; cv->cv_tot_len<<=EXPANED_VAL; cv->cv_pdata=realloc(cv->cv_pdata,cv->cv_tot_len*cv->cv_size); if(!cv->cv_pdata) { cv->cv_pdata=pd_sav; cv->cv_tot_len>>=EXPANED_VAL; returnCVEPUSHBACK; } } memcpy(cv->cv_pdata+cv->cv_len*cv->cv_size,memb,cv->cv_size); cv->cv_len++; returnCVESUCCESS; } intcvector_popback(constcvectorcv,void*memb) { if(cv->cv_len<=0)returnCVEPOPBACK; cv->cv_len--; memcpy(memb,cv->cv_pdata+cv->cv_len*cv->cv_size,cv->cv_size); if((cv->cv_tot_len>=(MIN_LEN<<REDUSED_VAL)) &&(cv->cv_len<=(cv->cv_tot_len>>REDUSED_VAL))) { void*pd_sav=cv->cv_pdata; cv->cv_tot_len>>=EXPANED_VAL; cv->cv_pdata=realloc(cv->cv_pdata,cv->cv_tot_len*cv->cv_size); if(!cv->cv_pdata) { cv->cv_tot_len<<=EXPANED_VAL; cv->cv_pdata=pd_sav; returnCVEPOPBACK; } } returnCVESUCCESS; } size_tcvector_iter_at(constcvectorcv,citeratoriter) { CWARNING_ITER(cv,iter,__FILE__,__func__,__LINE__); return(iter-cv->cv_pdata)/cv->cv_size; } intcvector_iter_val(constcvectorcv,citeratoriter,void*memb) { CWARNING_ITER(cv,iter,__FILE__,__func__,__LINE__); memcpy(memb,iter,cv->cv_size); return0; } citeratorcvector_begin(constcvectorcv) { returncv->cv_pdata; } citeratorcvector_end(constcvectorcv) { returncv->cv_pdata+(cv->cv_size*cv->cv_len); } staticinlinevoidcvmemove_foreward(constcvectorcv,void*from,void*to) { size_tsize=cv->cv_size; void*p; for(p=to;p>=from;p-=size)memcpy(p+size,p,size); return; } staticinlinevoidcvmemove_backward(constcvectorcv,void*from,void*to) { memcpy(from,from+cv->cv_size,to-from); return; } intcvector_insert(constcvectorcv,citeratoriter,void*memb) { CWARNING_ITER(cv,iter,__FILE__,__func__,__LINE__); if(cv->cv_len>=cv->cv_tot_len) { void*pd_sav=cv->cv_pdata; cv->cv_tot_len<<=EXPANED_VAL; cv->cv_pdata=realloc(cv->cv_pdata,cv->cv_tot_len*cv->cv_size); if(!cv->cv_pdata) { cv->cv_pdata=pd_sav; cv->cv_tot_len>>=EXPANED_VAL; returnCVEINSERT; } } cvmemove_foreward(cv,iter,cv->cv_pdata+cv->cv_len*cv->cv_size); memcpy(iter,memb,cv->cv_size); cv->cv_len++; returnCVESUCCESS; } intcvector_insert_at(constcvectorcv,size_tindex,void*memb) { citeratoriter; if(index>=cv->cv_tot_len) { cv->cv_len=index+1; while(cv->cv_len>=cv->cv_tot_len)cv->cv_tot_len<<=EXPANED_VAL; cv->cv_pdata=realloc(cv->cv_pdata,cv->cv_tot_len*cv->cv_size); iter=cv->cv_pdata+cv->cv_size*index; memcpy(iter,memb,cv->cv_size); } else { iter=cv->cv_pdata+cv->cv_size*index; cvector_insert(cv,iter,memb); } return0; } citeratorcvector_next(constcvectorcv,citeratoriter) { returniter+cv->cv_size; } intcvector_val(constcvectorcv,citeratoriter,void*memb) { memcpy(memb,iter,cv->cv_size); return0; } intcvector_val_at(constcvectorcv,size_tindex,void*memb) { memcpy(memb,cv->cv_pdata+index*cv->cv_size,cv->cv_size); return0; } intcvector_rm(constcvectorcv,citeratoriter) { citeratorfrom; citeratorend; CWARNING_ITER(cv,iter,__FILE__,__func__,__LINE__); from=iter; end=cvector_end(cv); memcpy(from,from+cv->cv_size,end-from); cv->cv_len--; if((cv->cv_tot_len>=(MIN_LEN<<REDUSED_VAL)) &&(cv->cv_len<=(cv->cv_tot_len>>REDUSED_VAL))) { void*pd_sav=cv->cv_pdata; cv->cv_tot_len>>=EXPANED_VAL; cv->cv_pdata=realloc(cv->cv_pdata,cv->cv_tot_len*cv->cv_size); if(!cv->cv_pdata) { cv->cv_tot_len<<=EXPANED_VAL; cv->cv_pdata=pd_sav; returnCVERM; } } returnCVESUCCESS; } intcvector_rm_at(constcvectorcv,size_tindex) { citeratoriter; iter=cv->cv_pdata+cv->cv_size*index; CWARNING_ITER(cv,iter,__FILE__,__func__,__LINE__); returncvector_rm(cv,iter); } voidcv_info(constcvectorcv) { printf("/n/ntot:%s:%d/n",__func__,cv->cv_tot_len); printf("len:%s:%d/n",__func__,cv->cv_len); printf("size:%s:%d/n/n",__func__,cv->cv_size); return; } voidcv_print(constcvectorcv) { intnum; citeratoriter; if(cvector_length(cv)==0) fprintf(stderr,"file:%sfunc:%sline:%derror,nulllengthcvector!!/n",__FILE__,__func__,__LINE__); for(iter=cvector_begin(cv); iter!=cvector_end(cv); iter=cvector_next(cv,iter)) { cvector_iter_val(cv,iter,&num); printf("var:%dat:%d/n",num,cvector_iter_at(cv,iter)); } return; }
改进版
上面那份代码是在Linux下写的,如果是在Windows的VisulC++环境下编译似乎会出些问题,所以特别做了个改进版:
下面是更新后的代码:
cvector.h
#ifndef__CVECTOR_H__ #define__CVECTOR_H__ #include<stdio.h> #include<stdlib.h> #include<string.h> #defineMIN_LEN256 #defineCVEFAILED-1 #defineCVESUCCESS0 #defineCVEPUSHBACK1 #defineCVEPOPBACK2 #defineCVEINSERT3 #defineCVERM4 #defineEXPANED_VAL1 #defineREDUSED_VAL2 typedefvoid*citerator; typedefstruct_cvector*cvector; #ifdef__cplusplus extern"C"{ #endif cvectorcvector_create(constsize_tsize); voidcvector_destroy(constcvectorcv); size_tcvector_length(constcvectorcv); intcvector_pushback(constcvectorcv,void*memb); intcvector_popback(constcvectorcv,void*memb); size_tcvector_iter_at(constcvectorcv,citeratoriter); intcvector_iter_val(constcvectorcv,citeratoriter,void*memb); citeratorcvector_begin(constcvectorcv); citeratorcvector_end(constcvectorcv); citeratorcvector_next(constcvectorcv,citeratoriter); intcvector_val_at(constcvectorcv,size_tindex,void*memb); intcvector_insert(constcvectorcv,citeratoriter,void*memb); intcvector_insert_at(constcvectorcv,size_tindex,void*memb); intcvector_rm(constcvectorcv,citeratoriter); intcvector_rm_at(constcvectorcv,size_tindex); /*fortest*/ voidcv_info(constcvectorcv); voidcv_print(constcvectorcv); #ifdef__cplusplus } #endif #endif/*EOFfilecvector.h*/
cvector.c
#include"cvector.h" #ifndef__gnu_linux__ #define__func__"unknown" #defineinline__forceinline #endif #defineCWARNING_ITER(cv,iter,file,func,line)\ do{\ if((cvector_begin(cv)>iter)||(cvector_end(cv)<=iter)){\ fprintf(stderr,"var("#iter")warngoutofrange,"\ "atfile:%sfunc:%sline:%d!!\n",file,func,line);\ returnCVEFAILED;\ }\ }while(0) struct_cvector { void*cv_pdata; size_tcv_len,cv_tot_len,cv_size; }; cvectorcvector_create(constsize_tsize) { cvectorcv=(cvector)malloc(sizeof(struct_cvector)); if(!cv)returnNULL; cv->cv_pdata=malloc(MIN_LEN*size); if(!cv->cv_pdata) { free(cv); returnNULL; } cv->cv_size=size; cv->cv_tot_len=MIN_LEN; cv->cv_len=0; returncv; } voidcvector_destroy(constcvectorcv) { free(cv->cv_pdata); free(cv); return; } size_tcvector_length(constcvectorcv) { returncv->cv_len; } intcvector_pushback(constcvectorcv,void*memb) { if(cv->cv_len>=cv->cv_tot_len) { void*pd_sav=cv->cv_pdata; cv->cv_tot_len<<=EXPANED_VAL; cv->cv_pdata=realloc(cv->cv_pdata,cv->cv_tot_len*cv->cv_size); if(!cv->cv_pdata) { cv->cv_pdata=pd_sav; cv->cv_tot_len>>=EXPANED_VAL; returnCVEPUSHBACK; } } memcpy((char*)cv->cv_pdata+cv->cv_len*cv->cv_size,memb,cv->cv_size); cv->cv_len++; returnCVESUCCESS; } intcvector_popback(constcvectorcv,void*memb) { if(cv->cv_len<=0)returnCVEPOPBACK; cv->cv_len--; memcpy(memb,(char*)cv->cv_pdata+cv->cv_len*cv->cv_size,cv->cv_size); if((cv->cv_tot_len>=(MIN_LEN<<REDUSED_VAL)) &&(cv->cv_len<=(cv->cv_tot_len>>REDUSED_VAL))) { void*pd_sav=cv->cv_pdata; cv->cv_tot_len>>=EXPANED_VAL; cv->cv_pdata=realloc(cv->cv_pdata,cv->cv_tot_len*cv->cv_size); if(!cv->cv_pdata) { cv->cv_tot_len<<=EXPANED_VAL; cv->cv_pdata=pd_sav; returnCVEPOPBACK; } } returnCVESUCCESS; } size_tcvector_iter_at(constcvectorcv,citeratoriter) { CWARNING_ITER(cv,iter,__FILE__,__func__,__LINE__); return((char*)iter-(char*)cv->cv_pdata)/cv->cv_size; } intcvector_iter_val(constcvectorcv,citeratoriter,void*memb) { CWARNING_ITER(cv,iter,__FILE__,__func__,__LINE__); memcpy(memb,iter,cv->cv_size); return0; } citeratorcvector_begin(constcvectorcv) { returncv->cv_pdata; } citeratorcvector_end(constcvectorcv) { return(char*)cv->cv_pdata+(cv->cv_size*cv->cv_len); } staticinlinevoidcvmemove_foreward(constcvectorcv,void*from,void*to) { size_tsize=cv->cv_size; char*p; for(p=(char*)to;p>=(char*)from;p-=size)memcpy(p+size,p,size); return; } staticinlinevoidcvmemove_backward(constcvectorcv,void*from,void*to) { memcpy(from,(char*)from+cv->cv_size,(char*)to-(char*)from); return; } intcvector_insert(constcvectorcv,citeratoriter,void*memb) { CWARNING_ITER(cv,iter,__FILE__,__func__,__LINE__); if(cv->cv_len>=cv->cv_tot_len) { void*pd_sav=cv->cv_pdata; cv->cv_tot_len<<=EXPANED_VAL; cv->cv_pdata=realloc(cv->cv_pdata,cv->cv_tot_len*cv->cv_size); if(!cv->cv_pdata) { cv->cv_pdata=pd_sav; cv->cv_tot_len>>=EXPANED_VAL; returnCVEINSERT; } } cvmemove_foreward(cv,iter,(char*)cv->cv_pdata+cv->cv_len*cv->cv_size); memcpy(iter,memb,cv->cv_size); cv->cv_len++; returnCVESUCCESS; } intcvector_insert_at(constcvectorcv,size_tindex,void*memb) { citeratoriter; if(index>=cv->cv_tot_len) { cv->cv_len=index+1; while(cv->cv_len>=cv->cv_tot_len)cv->cv_tot_len<<=EXPANED_VAL; cv->cv_pdata=realloc(cv->cv_pdata,cv->cv_tot_len*cv->cv_size); iter=(char*)cv->cv_pdata+cv->cv_size*index; memcpy(iter,memb,cv->cv_size); } else { iter=(char*)cv->cv_pdata+cv->cv_size*index; cvector_insert(cv,iter,memb); } return0; } citeratorcvector_next(constcvectorcv,citeratoriter) { return(char*)iter+cv->cv_size; } intcvector_val(constcvectorcv,citeratoriter,void*memb) { memcpy(memb,iter,cv->cv_size); return0; } intcvector_val_at(constcvectorcv,size_tindex,void*memb) { memcpy(memb,(char*)cv->cv_pdata+index*cv->cv_size,cv->cv_size); return0; } intcvector_rm(constcvectorcv,citeratoriter) { citeratorfrom; citeratorend; CWARNING_ITER(cv,iter,__FILE__,__func__,__LINE__); from=iter; end=cvector_end(cv); memcpy(from,(char*)from+cv->cv_size,(char*)end-(char*)from); cv->cv_len--; if((cv->cv_tot_len>=(MIN_LEN<<REDUSED_VAL)) &&(cv->cv_len<=(cv->cv_tot_len>>REDUSED_VAL))) { void*pd_sav=cv->cv_pdata; cv->cv_tot_len>>=EXPANED_VAL; cv->cv_pdata=realloc(cv->cv_pdata,cv->cv_tot_len*cv->cv_size); if(!cv->cv_pdata) { cv->cv_tot_len<<=EXPANED_VAL; cv->cv_pdata=pd_sav; returnCVERM; } } returnCVESUCCESS; } intcvector_rm_at(constcvectorcv,size_tindex) { citeratoriter; iter=(char*)cv->cv_pdata+cv->cv_size*index; CWARNING_ITER(cv,iter,__FILE__,__func__,__LINE__); returncvector_rm(cv,iter); } voidcv_info(constcvectorcv) { printf("\n\ntot:%s:%d\n",__func__,cv->cv_tot_len); printf("len:%s:%d\n",__func__,cv->cv_len); printf("size:%s:%d\n\n",__func__,cv->cv_size); return; } voidcv_print(constcvectorcv) { intnum; citeratoriter; if(cvector_length(cv)==0) fprintf(stderr,"file:%sfunc:%sline:%derror,nulllengthcvector!!\n",__FILE__,__func__,__LINE__); for(iter=cvector_begin(cv); iter!=cvector_end(cv); iter=cvector_next(cv,iter)) { cvector_iter_val(cv,iter,&num); printf("var:%dat:%d\n",num,cvector_iter_at(cv,iter)); } return; }
main.cpp
#include"cvector.h" intmain() { inti=1; cvectorcv=cvector_create(sizeof(int)); cvector_pushback(cv,&i); cvector_pushback(cv,&i); cvector_pushback(cv,&i); cvector_pushback(cv,&i); cv_print(cv); cvector_destroy(cv); return0; }