A good C equivalent of STL vector?

后端 未结 7 2065
悲&欢浪女
悲&欢浪女 2021-02-02 12:54

I\'ve noticed that at several places in our code base we use dynamically expanding arrays, i.e. a base array coupled with an element counter and a \"max elements\" value.

7条回答
  •  长发绾君心
    2021-02-02 13:24

    here a simple vector-replacement, its ONE function for all, its strictly C89 and threadsafe; libs are too difficult for me, i use my own; no performance, but easy to use

    /* owner-structs too */
    typedef struct {
      char name[20],city[20];
      int salary;
    } My,*Myp;
    
    typedef char Str80[80];
    
    /* add here your type with its size */
    typedef enum {SPTR,INT=sizeof(int),DOUBLE=sizeof(double),S80=sizeof(Str80),MY=sizeof(My)} TSizes;
    
    typedef enum {ADD,LOOP,COUNT,FREE,GETAT,GET,REMOVEAT,REMOVE} Ops;
    
    void *dynarray(char ***root,TSizes ts,Ops op,void *in,void *out)
    {
      size_t d=0,s=in?ts?ts:strlen((char*)in)+1:0;
      char **r=*root;
      while( r && *r++ ) ++d;
      switch(op) {
      case ADD:   if( !*root ) *root=calloc(1,sizeof r);
                  *root=realloc(*root,(d+2)*sizeof r);
                  memmove((*root)+1,*root,(d+1)*sizeof r);
                  memcpy(**root=malloc(s),in,s);
                  break;
      case LOOP:  while( d-- ) ((void (*)(char*))in)((*root)[d]); break;
      case COUNT: return *(int*)out=d,out;
      case FREE:  if(r) {
                    ++d; while( d-- ) realloc((*root)[d],0);
                    free(*root);*root=0;
                  } break;
      case GETAT: { size_t i=*(size_t*)in;
                    if(r && i<=--d)
                      return (*root)[d-i];
                  } break;
      case GET:   { int i=-1;
                    while( ++i,d-- )
                    if( !(ts?memcmp:strncmp)(in,(*root)[d],s) )
                      return *(int*)out=i,out;
                    return *(int*)out=-1,out;
                  }
      case REMOVEAT: { size_t i=*(size_t*)in;
                       if(r && i<=--d) {
                         free((*root)[d-i]);
                         memmove(&(*root)[d-i],&(*root)[d-i+1],(d-i+1)*sizeof r);
                         return in;
                       }
                     } break;
      case REMOVE: while( *(int*)dynarray(root,ts,GET,in,&d)>=0 )
                     dynarray(root,ts,REMOVEAT,&d,0);
      }
      return 0;
    }
    
    void outmy(Myp s)
    {
      printf("\n%s,%s,%d",s->name,s->city,s->salary);
    }
    
    main()
    {
      My    z[]={{"Buffet","Omaha",INT_MAX},{"Jobs","Palo Alto",1},{"Madoff","NYC",INT_MIN}};
      Str80 y[]={ "123","456","7890" };
      char **ptr=0;
      int x=1;
    
      /* precondition for first use: ptr==NULL */
      dynarray(&ptr,SPTR,ADD,"test1.txt",0);
      dynarray(&ptr,SPTR,ADD,"test2.txt",0);
      dynarray(&ptr,SPTR,ADD,"t3.txt",0);
    
      dynarray(&ptr,SPTR,REMOVEAT,&x,0); /* remove at index/key ==1 */
      dynarray(&ptr,SPTR,REMOVE,"test1.txt",0);
    
      dynarray(&ptr,SPTR,GET,"t3.txt",&x);
      dynarray(&ptr,SPTR,LOOP,puts,0);
    
      /* another option for enumerating */
      dynarray(&ptr,SPTR,COUNT,0,&x);
        while( x-- )
          puts(ptr[x]);
      dynarray(&ptr,SPTR,FREE,0,0); /* frees all mallocs and set ptr to NULL */
    
      /* start for another (user)type */
      dynarray(&ptr,S80,ADD,y[0],0);
      dynarray(&ptr,S80,ADD,y[1],0);
      dynarray(&ptr,S80,ADD,y[2],0);
      dynarray(&ptr,S80,ADD,y[0],0);
      dynarray(&ptr,S80,LOOP,puts,0);
      dynarray(&ptr,S80,FREE,0,0); /* frees all mallocs and set ptr to NULL */
    
      /* start for another (user)struct-type */
      dynarray(&ptr,MY,ADD,&z[0],0);
      dynarray(&ptr,MY,ADD,&z[1],0);
      dynarray(&ptr,MY,ADD,&z[2],0);
      dynarray(&ptr,MY,ADD,&z[0],0);
      dynarray(&ptr,MY,LOOP,outmy,0);
      dynarray(&ptr,MY,FREE,0,0);
    
      return 0;
    }
    

提交回复
热议问题