C编写的具有模板功能的Vector - 基于动态顺序数组
来源:互联网 发布:广联达预算软件购买 编辑:程序博客网 时间:2024/06/02 06:06
要点:
1. 要通过C来实现类似于C++中的Vector模板,常用的做法是使用typedef,但这么做的话无法实现C++中拷贝函数及析构函数的功能,而且还需要考虑包含头文件的顺序,即目标类型必须先于Vector定义。
2. 故可以考虑使用void *类型指针。
3. 对于指针来说,重要的不是类型,唯一重要的是这个指针所指向的内存区域中一个元素的大小是多少,如char *指针指向的内存区域一个元素占8位,short *则占16位,对于一些结构体指针来说,这个值可以是任意倍的字节。
4. 对于32位机器来说,每个指针本身的大小都是32位
总结如上要点,得出的解决办法是,
typedef void *vector_entry_ptr;typedef void (*vector_copy_func)(vector_entry_ptr, const vector_entry_ptr);typedef void (*vector_cleanup_func)(vector_entry_ptr); /* the parameter passed to clean_f is the address of the ith element */typedef struct _vector { vector_entry_ptr datap; unsigned long elementSize; unsigned long capacity; unsigned long count; vector_copy_func copy_f; vector_cleanup_func clean_f;} Vector, *VectorPtr;
声明一个这样的数据结构。
copy_f以及clean_f是函数指针,这里充当拷贝构造函数和析构函数的作用。可以使用memcpy和free作为默认行为(当他们为NULL的时候)。
具体操作见源代码:
vector.h
/* * Dynamic Allocated Array-Based Vector C Implementation * For The Teco Project * Copyright (C) 2010 milkyjing <milkyjing@gmail.com> * Auguest 11th, 2010 * * Modified for The RIXE Project at June 14th, 2011 by milkyjing * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * milkyjing * */#ifndef VECTOR_H#define VECTOR_H#pragma once#include <memory.h>#include <stdlib.h>typedef void *vector_entry_ptr;typedef void (*vector_copy_func)(vector_entry_ptr, const vector_entry_ptr);typedef void (*vector_cleanup_func)(vector_entry_ptr); /* the parameter passed to clean_f is the address of the ith element */typedef struct _vector { vector_entry_ptr datap; unsigned long elementSize; unsigned long capacity; unsigned long count; vector_copy_func copy_f; vector_cleanup_func clean_f;} Vector, *VectorPtr;typedef int (*vector_compare_func)(const vector_entry_ptr, const vector_entry_ptr); /* (src, key), `> 0' - left larger, `= 0' equal, `< 0', left smaller */typedef int (*vector_compare_interval_func)(const vector_entry_ptr, const vector_entry_ptr, const vector_entry_ptr); /* (start, end, key), the last parameter is key, `> 0' - key on the left, `= 0' in the interval, `< 0', key on the right */typedef void (*vector_traverse_func)(const vector_entry_ptr);#ifdef __cplusplusextern "C" {#endif /* __cplusplus */extern void vector_create(VectorPtr *pvptr, unsigned long elementSize, unsigned long elements, vector_copy_func copy_f, vector_cleanup_func clean_f);extern unsigned long vector_get_size(const VectorPtr vptr);extern const vector_entry_ptr vector_get_buf(const VectorPtr vptr);extern int vector_assign(VectorPtr vptr, unsigned long i, const vector_entry_ptr element);/* element can be NULL, if so, we will not make a copy to element. the return value is the address of the element retrieved */extern const vector_entry_ptr vector_retrieve(const VectorPtr vptr, unsigned long i, vector_entry_ptr element);extern void vector_push_back(VectorPtr vptr, const vector_entry_ptr element);extern int vector_pop_back(VectorPtr vptr);extern void vector_clear(VectorPtr vptr);extern void vector_destroy(VectorPtr vptr);/* UTILITY FUNCTIONS */extern void vector_traverse(const VectorPtr vptr, vector_traverse_func traverse_func);extern void vector_bulbsort(VectorPtr vptr, vector_compare_func compare_func);/* s should always be 0, and l should always be vptr->count - 1, note that both s and l should be signed rather than unsigned */extern void vector_quicksort(VectorPtr vptr, long s, long l, vector_compare_func compare_func);/* if element = NULL, it won't copy the result to it, just return the index, which somehow increase performance */extern long vector_sequential_search(const VectorPtr vptr, const vector_entry_ptr key, vector_compare_func compare_func, vector_entry_ptr element);/* if element = NULL, it won't copy the result to it, just return the index, which somehow increase performance */extern long vector_binary_search(const VectorPtr vptr, const vector_entry_ptr key, vector_compare_func compare_func, vector_entry_ptr element);/* returns the left side element (start) */extern long vector_binary_search_interval(const VectorPtr vptr, const vector_entry_ptr key, vector_compare_interval_func compare_interval_func);#ifdef __cplusplus}#endif#endif /* VECTOR_H */
/* * Copyright (C) 2011 milkyjing <milkyjing@gmail.com> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * milkyjing * */#include "vector.h"void vector_create(VectorPtr *pvptr, unsigned long elementSize, unsigned long elements, vector_copy_func copy_f, vector_cleanup_func clean_f) { VectorPtr vptr; vptr = (VectorPtr)malloc(sizeof(Vector)); vptr->elementSize = elementSize; vptr->capacity = elements; vptr->count = elements; vptr->copy_f = copy_f; /* if copy_f = NULL, default copy function will be applied */ vptr->clean_f = clean_f; /* if clean_f = NULL, default cleanup function will be applied */ if (elements > 0) { unsigned long size = vptr->capacity * vptr->elementSize; vptr->datap = (vector_entry_ptr)malloc(size); memset(vptr->datap, 0, size); } else vptr->datap = NULL; *pvptr = vptr;}unsigned long vector_get_size(const VectorPtr vptr) { return vptr->count;}const vector_entry_ptr vector_get_buf(const VectorPtr vptr) { return (const vector_entry_ptr)vptr->datap;}int vector_assign(VectorPtr vptr, unsigned long i, const vector_entry_ptr element) { vector_entry_ptr oldElem; if (i >= vptr->count) return -1; oldElem = (unsigned char *)vptr->datap + i * vptr->elementSize; if (vptr->clean_f) vptr->clean_f(oldElem); if (vptr->copy_f) vptr->copy_f(oldElem, element); else memcpy(oldElem, element, vptr->elementSize); return 0;}const vector_entry_ptr vector_retrieve(const VectorPtr vptr, unsigned long i, vector_entry_ptr element) { vector_entry_ptr oldElem; if (i >= vptr->count) return NULL; oldElem = (unsigned char *)vptr->datap + i * vptr->elementSize; if (element) { /* make a copy */ if (vptr->copy_f) vptr->copy_f(element, oldElem); else memcpy(element, oldElem, vptr->elementSize); } return (const vector_entry_ptr)oldElem;}void vector_push_back(VectorPtr vptr, const vector_entry_ptr element) { vector_entry_ptr oldElem; if (vptr->count == vptr->capacity) { vptr->capacity += vptr->capacity / 2 + 1; vptr->datap = (vector_entry_ptr)realloc(vptr->datap, vptr->capacity * vptr->elementSize); } oldElem = (unsigned char *)vptr->datap + vptr->count * vptr->elementSize; if (vptr->copy_f) vptr->copy_f(oldElem, element); else memcpy(oldElem, element, vptr->elementSize); vptr->count++;}int vector_pop_back(VectorPtr vptr) { vector_entry_ptr oldElem; if (0 == vptr->count) return -1; oldElem = (unsigned char *)vptr->datap + (vptr->count - 1) * vptr->elementSize; if (vptr->clean_f) vptr->clean_f(oldElem); vptr->count--; return 0;}void vector_clear(VectorPtr vptr) { if (vptr->clean_f) { unsigned long i; for (i = 0; i < vptr->count; i++) vptr->clean_f((unsigned char *)vptr->datap + i * vptr->elementSize); /* the parameter passed to clean_f is the address of the ith element */ } free(vptr->datap); vptr->datap = NULL; vptr->capacity = 0; vptr->count = 0; /* other data members should stay unchanged */}void vector_destroy(VectorPtr vptr) { vector_clear(vptr); free(vptr);}/* UTILITY FUNCTIONS */void vector_traverse(const VectorPtr vptr, vector_traverse_func traverse_func) { unsigned long i; for (i = 0; i < vptr->count; i++) traverse_func((unsigned char *)vptr->datap + i * vptr->elementSize);}void vector_bulbsort(VectorPtr vptr, vector_compare_func compare_func) { unsigned long i, j; vector_entry_ptr p1, p2, pt; pt = (vector_entry_ptr)malloc(vptr->elementSize); /* use as temp */ for (i = 0; i < vptr->count; i++) { for (j = 0; j < vptr->count - i - 1; j++) { p1 = (unsigned char *)vptr->datap + j * vptr->elementSize; p2 = (unsigned char *)p1 + vptr->elementSize; if (compare_func(p1, p2) > 0) { memcpy(pt, p1, vptr->elementSize); memcpy(p1, p2, vptr->elementSize); memcpy(p2, pt, vptr->elementSize); } } } free(pt);}/* s should always be 0, and l should always be vptr->count - 1, note that both s and l should be signed rather than unsigned */void vector_quicksort(VectorPtr vptr, long s, long l, vector_compare_func compare_func) { long i, j; vector_entry_ptr pt; i = s; j = l; pt = (vector_entry_ptr)malloc(vptr->elementSize); /* use as temp */ if (s < l) { memcpy(pt, (unsigned char *)vptr->datap + s * vptr->elementSize, vptr->elementSize); while (i != j) { while (j > i && compare_func((unsigned char *)vptr->datap + j * vptr->elementSize, pt) > 0) j--; memcpy((unsigned char *)vptr->datap + i * vptr->elementSize, (unsigned char *)vptr->datap + j * vptr->elementSize, vptr->elementSize); while (i < j && compare_func((unsigned char *)vptr->datap + i * vptr->elementSize, pt) < 0) i++; memcpy((unsigned char *)vptr->datap + j * vptr->elementSize, (unsigned char *)vptr->datap + i * vptr->elementSize, vptr->elementSize); } memcpy((unsigned char *)vptr->datap + i * vptr->elementSize, pt, vptr->elementSize); vector_quicksort(vptr, s, i - 1, compare_func); vector_quicksort(vptr, i + 1, l, compare_func); } free(pt);}long vector_sequential_search(const VectorPtr vptr, const vector_entry_ptr key, vector_compare_func compare_func, vector_entry_ptr element) { unsigned long i; vector_entry_ptr temp; for (i = 0; i < vptr->count; i++) { temp = (unsigned char *)vptr->datap + i * vptr->elementSize; if (compare_func(key, temp) == 0) { if (element) { if (vptr->copy_f) vptr->copy_f(element, temp); else memcpy(element, temp, vptr->elementSize); } return i; } } return -1;}long vector_binary_search(const VectorPtr vptr, const vector_entry_ptr key, vector_compare_func compare_func, vector_entry_ptr element) { long bottom, top, mid; vector_entry_ptr temp; bottom = 0; top = vptr->count - 1; while (bottom < top) { mid = (top + bottom) / 2; temp = (unsigned char *)vptr->datap + mid * vptr->elementSize; if (compare_func(temp, key) < 0) bottom = mid + 1; else top = mid; } temp = (unsigned char *)vptr->datap + top * vptr->elementSize; if (bottom > top || compare_func(temp, key) != 0) return -1; if (element) { if (vptr->copy_f) vptr->copy_f(element, temp); else memcpy(element, temp, vptr->elementSize); } return top;}long vector_binary_search_interval(const VectorPtr vptr, const vector_entry_ptr key, vector_compare_interval_func compare_interval_func) { long bottom, top, mid; vector_entry_ptr start, end; bottom = 0; top = vptr->count - 2; while (bottom < top) { mid = (top + bottom) / 2; start = (unsigned char *)vptr->datap + mid * vptr->elementSize; end = (unsigned char *)start + vptr->elementSize; if (compare_interval_func(start, end, key) < 0) bottom = mid + 1; else top = mid; } start = (unsigned char *)vptr->datap + top * vptr->elementSize; end = (unsigned char *)start + vptr->elementSize; if (bottom > top || compare_interval_func(start, end, key) != 0) return -1; return top;}
- C编写的具有模板功能的Vector - 基于动态顺序数组
- 用VC编写具有动态换肤功能的应用程序
- 用VC编写具有动态换肤功能的应用程序
- 用VC编写具有动态换肤功能的应用程序
- 用vc编写具有动态换肤功能的应用程序
- 用VC编写具有动态换肤功能的应用程序
- 用VC编写具有动态换肤功能的应用程序
- vector动态数组的应用
- 模板容器类的实现一(基于动态数组)
- 具有打印功能的 Listview 类(C#)
- 具有打印功能的 Listview 类(C#)
- 具有打印功能的 Listview 类(C#)
- 【c++】模板实现动态Vector
- 1-2.编写一个具有计算功能的angular程序
- vector动态数组邻接表--功能更强大的邻接表
- 【C++】用模板实现顺序表Vector
- C++primer学习:拷贝控制(5):动态内存管理类_编写自己的vector
- 具有自动提示功能的菜单(AutoCompleteTextView与数组)
- 推荐一些计算机视觉相关的书籍
- IEC,ASTM,ISO,DIN,JIS等国际标准网站
- 无法远程登入MySQL Server[转帖]
- U盘识别操作
- java枚举和switch案例
- C编写的具有模板功能的Vector - 基于动态顺序数组
- jstl 下拉菜单
- 1、小型电话拨号器源码
- CEasySize
- Windows 中的软连接和硬连接
- Redhat ntfs driver complie
- Composite UI Application Block开发的介绍
- 字符串相加
- tomcat 项目访问去掉端口和项目名称