Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
一个好的STL向量的C等价物?_C_C89 - Fatal编程技术网

一个好的STL向量的C等价物?

一个好的STL向量的C等价物?,c,c89,C,C89,我注意到,在代码库中的几个地方,我们使用了动态扩展数组,即一个与元素计数器和“max elements”值耦合的基数组 出于通常面向对象的原因,我想用一个通用的数据结构和实用程序函数替换它们。 数组元素可以是基本数据类型或结构,我需要快速随机访问元素,最好是类型安全的实现 因此,基本上,我想使用的是STL向量,但代码库仅限于C89,因此我必须想出其他方法:-) 我考虑了一下,起草了这份初稿,只是为了说明我的目标: /* Type-safe dynamic list in C89 */ #def

我注意到,在代码库中的几个地方,我们使用了动态扩展数组,即一个与元素计数器和“max elements”值耦合的基数组

出于通常面向对象的原因,我想用一个通用的数据结构和实用程序函数替换它们。 数组元素可以是基本数据类型或结构,我需要快速随机访问元素,最好是类型安全的实现

因此,基本上,我想使用的是STL向量,但代码库仅限于C89,因此我必须想出其他方法:-)

我考虑了一下,起草了这份初稿,只是为了说明我的目标:

/* Type-safe dynamic list in C89 */

#define list_declare(type) typedef struct _##type##_list_t { type * base_array; size_t elements; size_t max_size; } type##_list_t
#define list(type) type##_list_t
#define list_new(type, initial_size) { calloc(initial_size, sizeof(type)), 0, initial_size }
#define list_free(list) free(list.base_array)
#define list_set(list, place, element) if ( list.elements < list.max_size ) { list.base_array[place] = element; } else { /* Array index out of bounds */ }
#define list_add(list, element) if ( list.elements < list.max_size ) { list.base_array[list.elements++] = element; } else { /* Expand array then add */ }
#define list_get(list, n) list.base_array[n]

/* Sample usage: */

list_declare(int);

int main(void)
{
    list(int) integers = list_new(int, 10);
    printf("list[0] = %d\n", list_get(integers, 0));
    list_add(integers, 4);
    printf("list[0] = %d\n", list_get(integers, 0));
    list_set(integers, 0, 3);
    printf("list[0] = %d\n", list_get(integers, 0));
    list_free(integers);

    return EXIT_SUCCESS;
}
/*在C89中键入安全动态列表*/
#定义列表\声明(类型)类型定义结构\类型\类型\列表\类型*基数组;大小\元素;大小\最大\大小;}类型\列表\类型
#定义列表(类型)类型
#定义list_new(type,initial_size){calloc(initial_size,sizeof(type)),0,initial_size}
#定义list\u free(list)free(list.base\u数组)
#如果(list.elements
…但是,肯定有其他人以前做过这件事。我知道FreeBSD sys/queue.h为一些不同的队列实现了类似的概念,但我找不到任何类似于数组的实现


这里有人更聪明吗?

glib提供了一种类型,它实现了一个动态增长的数组。如果您可以使用外部第三方库,glib几乎总是C的“标准”库的好选择。它为所有基本数据结构、unicode字符串、日期和时间值等提供类型。

还有sglib,它以通用方式实现各种列表、hashmaps和RBtree(即通过对类型进行专门化)。还有一个用于阵列的快速排序功能:


这里是一个简单的向量替换,它的一个功能是所有的,它的严格的C89和线程安全; LIB对我来说太难了,我用我自己的; 没有性能,但易于使用

/* 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;
}
/*所有者结构也是*/
类型定义结构{
字符名称[20],城市[20];
国际工资;
}My,*Myp;
typedef char Str80[80];
/*在此添加您的类型及其大小*/
typedef枚举{SPTR,INT=sizeof(INT),DOUBLE=sizeof(DOUBLE),S80=sizeof(Str80),MY=sizeof(MY)}TSizes;
typedef枚举{ADD,LOOP,COUNT,FREE,GETAT,GET,REMOVEAT,REMOVE}Ops;
void*dynarray(字符***根、TSTS、Ops op、void*in、void*out)
{
尺寸d=0,s=in?ts?ts:strlen((char*)in)+1:0;
char**r=*根;
而(r&*r+++++++d,;
开关(op){
案例添加:如果(!*root)*root=calloc(1,sizeof r);
*root=realloc(*root,(d+2)*r的大小);
memmove((*根)+1,*根,(d+1)*大小r);
memcpy(**root=malloc,in,s);
打破
大小写循环:while(d-)((void(*)(char*))in)((*root)[d]);break;
案例计数:return*(int*)out=d,out;
无案例:如果(r){
++d、 而(d--)realloc((*根)[d],0);
自由(*根);*根=0;
}中断;
case GETAT:{size\u t i=*(size\u t*)in;
if(r&&iname,s->city,s->salary);
}
main()
{
我的z[]={{“自助餐”,“奥马哈”,国际马克斯},{“乔布斯”,“帕洛阿尔托”,1},{“麦道夫”,“纽约”,国际马克斯};
str80y[]={“123”、“456”、“7890”};
字符**ptr=0;
int x=1;
/*首次使用的先决条件:ptr==NULL*/
dynarray(&ptr,SPTR,添加“test1.txt”,0);
dynarray(&ptr,SPTR,添加“test2.txt”,0);
dynarray(&ptr,SPTR,添加“t3.txt”,0);
dynarray(&ptr,SPTR,REMOVEAT,&x,0);/*在索引处删除/key==1*/
dynarray(&ptr,SPTR,REMOVE,“test1.txt”,0);
dynarray(&ptr、SPTR、GET、“t3.txt”和&x);
dynarray(&ptr,SPTR,LOOP,put,0);
/*枚举的另一个选项*/
动态数组(&ptr、SPTR、计数、0和x);
而(x-)
看跌期权(ptr[x]);
dynarray(&ptr,SPTR,FREE,0,0);/*释放所有malloc并将ptr设置为NULL*/
/*另一(用户)类型的启动*/
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,循环,puts,0);
dynarray(&ptr,S80,FREE,0,0);/*释放所有malloc并将ptr设置为NULL*/
/*启动另一个(用户)结构类型*/
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);
返回0;
}

我通常使用自己的代码来实现这样的目的,就像你一样。这并不特别困难,但如果没有一个完整的OO框架,就很难实现类型安全等功能


如前所述,glib提供了您所需的功能-如果glib2对您来说太大,您仍然可以使用glib1.2。它非常旧,但没有外部依赖项(如果您需要线程支持,则pthread除外)。如果需要,该代码还可以集成到更大的项目中。它是LGPL许可的。

qLibc使用纯C实现了一个向量。数据结构允许它存储任何类型的对象,如(void*object),并为字符串、格式化字符串和整数类型提供方便的包装

下面是您的想法的示例代码

qvector_t *vector = qvector(QVECTOR_OPT_THREADSAFE);
vector->addstr(vector, "Hello");
vector->addstrf(vector, "World %d", 123);
char *finalstring = vector->tostring(vector);

printf("%s", finalstring);
free(finalstring)
vector->free(vector);
对于对象类型:

int a = 1, b = 2;
qvector_t *vector = qvector(QVECTOR_OPT_THREADSAFE);
vector->add(vector, (void *)&a, sizeof(int));
vector->add(vector, (void *)&b, sizeof(int));
int *finalarray = vector->toarray(vector);

printf("a = %d, b = %d", finalarray[0], finalarray[1]);
free(finalarray)
vector->free(vector);
注意)我制作这个示例代码只是为了供您参考,是从它的示例代码复制而来的。 它可能有打字错误

您可以在

查看完整的API参考,我是美国