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;
}

 

posted @ 2022-11-01 11:36  烟熏牛肉干  阅读(275)  评论(0编辑  收藏  举报