C语言实现C++语言的vector容器功能
开发编译环境(Windows环境):
1、Dev-C++/GCC
2、VS2022
运行结果如下图:
vector.c文件:
/* loop--AC/DC * loop--AC/DC */ #include "vector.h" #include <stdlib.h> #include <stdio.h> #include <assert.h> #include <string.h> void VectorNew(vector *v, int elemSize, VectorFreeFunction freefn, VectorCopyFunction copyfn, VectorCompareFunction cmpfn) { v->elemSize = elemSize; v->allocatedSize = 4; v->logicalSize = 0; v->data = malloc(v->elemSize * v->allocatedSize); assert(v->data != NULL); v->freefn = freefn; v->cmpfn = cmpfn; v->copyfn = copyfn; } void VectorDispose(vector *v) { if (v->freefn != NULL) { for (int i = 0; i < v->logicalSize; i++) { void *elemAddr = (char *)v->data + i * v->elemSize; v->freefn(elemAddr); } } free(v->data); //如果没有析构函数,直接free掉data数据 } void *VectorNth(const vector *v, int position) { assert(position >= 0); assert(position < v->logicalSize); return (char *)v->data + position * v->elemSize; } static void VectorGrow(vector *v) { v->data = realloc(v->data, 2 * v->allocatedSize * v->elemSize); assert(v->data != NULL); v->allocatedSize = 2 * v->allocatedSize; } void Vectorpush_back(vector *v, const void *elemAddr) { if (v->logicalSize == v->allocatedSize) VectorGrow(v); void *destAddr = (char *)v->data + v->logicalSize * v->elemSize; /* memcpy(destAddr, elemAddr, v->elemSize); */ if (v->copyfn != NULL) v->copyfn(destAddr, elemAddr); memcpy(destAddr, elemAddr, v->elemSize); v->logicalSize++; } void VectorDelete(vector *v, int position) { assert(position >= 0); assert(position < v->logicalSize); void *destAddr = (char *)v->data + position * v->elemSize; if (v->freefn != NULL) v->freefn(destAddr); int byteSize = (v->logicalSize - 1 - position) * v->elemSize; memmove(destAddr, (char *)destAddr + v->elemSize, byteSize); v->logicalSize--; } int VectorSize(const vector *v) { return v->logicalSize; } int VectorSearch(vector *v, const void *key, int startIndex) { assert(v->cmpfn != NULL); assert(startIndex >= 0); assert(startIndex <= v->logicalSize); void *base = (char *)v->data + startIndex * v->elemSize; int MAX = v->logicalSize - startIndex; int flag = -1; for (int i = 0; i < MAX; i++) { void *elemAddr = (char *)base + i * v->elemSize; if (0 == v->cmpfn(elemAddr, key)) { flag = i + startIndex; return flag; } } return flag; }
vector.h文件:
#pragma once #include <stdbool.h> //为了在C语言文件中使用bool变量,C99规定,在本文件中并未用到bool类型 #ifndef __VECTOR_H_ #define __VECTOR_H_ typedef int (*VectorCompareFunction)(const void *elemAddr1, const void *elemAddr2); typedef void (*VectorCopyFunction)(void *destAddr, const void *srcAddr); typedef void (*VectorFreeFunction)(void *elemAddr); typedef struct { void *data; //指向数据元素的指针 int elemSize; //每个元素占内存的大小 int allocatedSize; //已分配内存元素的大小 int logicalSize; //实际储存元素的个数 VectorFreeFunction freefn; //设置了一个free函数,根据数据地址释放不定长部分的内存空间 VectorCopyFunction copyfn; //提供源数据和目的数据的地址,为目的数据中不定长部分申请内存空间,将源数据中不定长部分拷贝到目的数据中不定长部分 VectorCompareFunction cmpfn; //根据参数地址比较两数据的大小 } vector; void VectorNew(vector *v, int elemSize, VectorFreeFunction freefn, VectorCopyFunction copyfn, VectorCompareFunction cmpfn); void VectorDispose(vector *v); void *VectorNth(const vector *v, int position); void VectorDelete(vector *v, int position); void Vectorpush_back(vector *v, const void *elemAddr); int VectorSize(const vector *v); int VectorSearch(vector *v, const void *key, int startIndex); #endif
main.c文件:
/* loop--AC/DC * loop--AC/DC */ #include "vector.h" #include <stdio.h> #include <string.h> #include <stdlib.h> /* 在main函数中定义自定义的析构函数,比较函数 * 复制函数 */ //整型比较函数 int INT_cmp(const void* elemAddr1, const void* elemAddr2) { return *(int*)elemAddr1 - *(int*)elemAddr2; } //浮点数比较函数,以double为例 int FLOAT_cmp(const void* elemAddr1, const void* elemAddr2) { return *(double*)elemAddr1 - *(double*)elemAddr2; } //字符型比较函数 int STR_cmp(const void* elemAddr1, const void* elemAddr2) { return strcmp(*(char**)elemAddr1, *(char**)elemAddr2); } //字符串的析构函数 void STR_free(void* elemAddr) { free(*(char**)elemAddr); } //字符串的复制函数 void STR_copy(void* destAddr, const void* srcAddr) { *(char**)destAddr = _strdup(*(char**)srcAddr); } int main() { printf("测试vector容器的使用,分为三类<整数,浮点数,字符串>\n\n"); //测试整数 printf("\n----------容器<整数>测试----------\n"); //声明容器 vector v1; //声明数组并赋值 int Array[] = { 1,2,3,4,5 }; //初始化容器 VectorNew(&v1, sizeof(int), NULL, NULL, INT_cmp); //不需要特定的free函数和copy函数,所以填NULL printf("整数容器<v1>初始化完毕\n"); printf("添加元素到容器<v1>\n"); for (int i = 0; i < 5; i++) { Vectorpush_back(&v1, &Array[i]); } //打印容器元素数量 v1.size(),用VectorSize(&v1)获取 printf("容器<v1>元素数量:%d\n", VectorSize(&v1)); //打印容器元素 printf("容器<v1>内容:"); //循环遍历出容器内的元素 for (int i = 0; i < VectorSize(&v1); i++) { printf("%d ", *(int*)VectorNth(&v1, i)); } //打印换行符 printf("\n"); printf("清空容器<v1>所有内容\n"); for (int i = 4; i >= 0; i--) { VectorDelete(&v1, i); } //打印容器元素数量 v1.size(),用VectorSize(&v1)获取 printf("容器<v1>元素数量:%d\n", VectorSize(&v1)); VectorDispose(&v1); //测试浮点数 printf("\n----------容器<浮点数>测试----------\n"); //声明容器 vector v2; //声明数组并赋值 double ArrayDouble[] = { 1.2,1.3,3.4,5.66,67.8888 }; //初始化容器 VectorNew(&v2, sizeof(double), NULL, NULL, FLOAT_cmp); printf("浮点数容器<v2>初始化完毕\n"); printf("添加元素到容器<v2>\n"); for (int i = 0; i < 5; i++) { Vectorpush_back(&v2, &ArrayDouble[i]); } //打印容器元素数量 v2.size(),用VectorSize(&v2)获取 printf("容器<v2>元素数量:%d\n", VectorSize(&v2)); //打印容器元素 printf("容器<v2>内容:"); //循环遍历出容器内的元素 for (int i = 0; i < VectorSize(&v2); i++) { printf("%.8lf ", *(double*)VectorNth(&v2, i)); } //打印换行符 printf("\n清空容器<v2>所有内容\n"); for (int i = (sizeof(ArrayDouble) / sizeof(double)) - 1; i >= 0; i--) { VectorDelete(&v2, i); } printf("容器<v2>元素数量:%d\n", VectorSize(&v2)); VectorDispose(&v2); //测试字符串 printf("\n----------容器<字符串>测试----------\n"); //声明数组并赋值 char* strArray[] = { "city", "world", "we", "broken", "people", "now" }; //声明容器 vector vStr; //初始化容器 VectorNew(&vStr, sizeof(char*), STR_free, STR_copy, STR_cmp); printf("字符串容器<vStr>初始化完毕\n"); printf("添加元素到容器<vStr>\n"); for (int i = 0; i < sizeof(strArray) / sizeof(char*); i++) { Vectorpush_back(&vStr, &strArray[i]); } //打印容器元素数量 vStr.size(),用VectorSize(&vStr)获取 printf("容器<vStr>元素数量:%d\n", VectorSize(&vStr)); //打印容器元素 printf("容器<vStr>内容:"); //循环遍历出容器内的元素 for (int i = 0; i < VectorSize(&vStr); i++) { printf("%s ", *(char**)VectorNth(&vStr, i)); } //打印换行符 printf("\n"); //声明要搜索的关键字符串 char* key = "broken"; //搜索关键字符串在容器里的索引并打印 printf("在容器<vStr>中搜索字符串'broken'索引:%d\n ", VectorSearch(&vStr, &key, 1)); VectorDispose(&vStr); return 0; }