首页 > 其他分享 >C语言实现 vector( 动态数组) 改进版(转)

C语言实现 vector( 动态数组) 改进版(转)

时间:2023-01-20 22:34:39浏览次数:44  
标签:__ cvector iter C语言 vector len 改进版 cv size

之所以再写一封邮件缘起于我写的《 C语言实现 vector( 动态数组)》这篇文章http://blog.csdn.net/dengxu11/article/details/5915857。

原来这个是在Linux下写的,多谢troublema的提议,我发现那份代码在windows上存在一些问题,故做了改进,以求在widnows上和Linux上都是OK的。

另外非常感谢troublema,没有他我发现不了这个存在的问题。

下面是更新后的代码:

//cvector.h


# ifndef __CVECTOR_H__
# define __CVECTOR_H__

# include <stdio.h>
# include <stdlib.h>
# include <string.h>

# define MIN_LEN 256
# define CVEFAILED -1
# define CVESUCCESS 0
# define CVEPUSHBACK 1
# define CVEPOPBACK 2
# define CVEINSERT 3
# define CVERM 4
# define EXPANED_VAL 1
# define REDUSED_VAL 2

typedef void *citerator;
typedef struct _cvector *cvector;

# ifdef __cplusplus
extern "C" {
# endif

cvector cvector_create (const size_t size );
void cvector_destroy (const cvector cv );
size_t cvector_length (const cvector cv );
int cvector_pushback (const cvector cv, void *memb );
int cvector_popback (const cvector cv, void *memb );
size_t cvector_iter_at (const cvector cv, citerator iter );
int cvector_iter_val (const cvector cv, citerator iter, void *memb);
citerator cvector_begin (const cvector cv );
citerator cvector_end (const cvector cv );
citerator cvector_next (const cvector cv, citerator iter );
int cvector_val_at (const cvector cv, size_t index, void *memb );
int cvector_insert (const cvector cv, citerator iter, void *memb);
int cvector_insert_at(const cvector cv, size_t index, void *memb );
int cvector_rm (const cvector cv, citerator iter );
int cvector_rm_at (const cvector cv, size_t index );

/* for test */
void cv_info (const cvector cv );
void cv_print (const cvector cv );

# ifdef __cplusplus
}
# endif

#endif /* EOF file cvector.h */

//cvector.c

#include "cvector.h"

#ifndef __gnu_linux__
#define __func__ "unknown"
#define inline __forceinline
#endif

# define CWARNING_ITER(cv, iter, file, func, line) \
do {\
if ((cvector_begin(cv) > iter) || (cvector_end(cv) <= iter)) {\
fprintf(stderr, "var(" #iter ") warng out of range, "\
"at file:%s func:%s line:%d!!\n", file, func, line);\
return CVEFAILED;\
}\
} while (0)

struct _cvector
{
void *cv_pdata;
size_t cv_len, cv_tot_len, cv_size;
};

cvector cvector_create(const size_t size)
{
cvector cv = (cvector)malloc(sizeof (struct _cvector));

if (!cv) return NULL;

cv->cv_pdata = malloc(MIN_LEN * size);

if (!cv->cv_pdata)
{
free(cv);
return NULL;
}

cv->cv_size = size;
cv->cv_tot_len = MIN_LEN;
cv->cv_len = 0;

return cv;
}

void cvector_destroy(const cvector cv)
{
free(cv->cv_pdata);
free(cv);
return;
}

size_t cvector_length(const cvector cv)
{
return cv->cv_len;
}

int cvector_pushback(const cvector cv, void *memb)
{
if (cv->cv_len >= cv->cv_tot_len)
{
void *pd_sav = cv->cv_pdata;
cv->cv_tot_len <<= EXPANED_VAL;
cv->cv_pdata = realloc(cv->cv_pdata, cv->cv_tot_len * cv->cv_size);

if (!cv->cv_pdata)
{
cv->cv_pdata = pd_sav;
cv->cv_tot_len >>= EXPANED_VAL;
return CVEPUSHBACK;
}
}

memcpy((char *)cv->cv_pdata + cv->cv_len * cv->cv_size, memb, cv->cv_size);
cv->cv_len++;

return CVESUCCESS;
}

int cvector_popback(const cvector cv, void *memb)
{
if (cv->cv_len <= 0) return CVEPOPBACK;

cv->cv_len--;
memcpy(memb, (char *)cv->cv_pdata + cv->cv_len * cv->cv_size, cv->cv_size);

if ((cv->cv_tot_len >= (MIN_LEN << REDUSED_VAL))
&& (cv->cv_len <= (cv->cv_tot_len >> REDUSED_VAL)))
{
void *pd_sav = cv->cv_pdata;
cv->cv_tot_len >>= EXPANED_VAL;
cv->cv_pdata = realloc(cv->cv_pdata, cv->cv_tot_len * cv->cv_size);

if (!cv->cv_pdata)
{
cv->cv_tot_len <<= EXPANED_VAL;
cv->cv_pdata = pd_sav;
return CVEPOPBACK;
}
}

return CVESUCCESS;
}

size_t cvector_iter_at(const cvector cv, citerator iter)
{
CWARNING_ITER(cv, iter, __FILE__, __func__, __LINE__);
return ((char *)iter - (char *)cv->cv_pdata) / cv->cv_size;
}

int cvector_iter_val(const cvector cv, citerator iter, void *memb)
{
CWARNING_ITER(cv, iter, __FILE__, __func__, __LINE__);
memcpy(memb, iter, cv->cv_size);
return 0;
}

citerator cvector_begin(const cvector cv)
{
return cv->cv_pdata;
}

citerator cvector_end(const cvector cv)
{
return (char *)cv->cv_pdata + (cv->cv_size * cv->cv_len);
}

static inline void cvmemove_foreward(const cvector cv, void *from, void *to)
{
size_t size = cv->cv_size;
char *p;
for (p = (char *)to; p >= (char *)from; p -= size) memcpy(p + size, p, size);
return;
}

static inline void cvmemove_backward(const cvector cv, void *from, void *to)
{
memcpy(from, (char *)from + cv->cv_size, (char *)to - (char *)from);
return;
}

int cvector_insert(const cvector cv, citerator iter, void *memb)
{
CWARNING_ITER(cv, iter, __FILE__, __func__, __LINE__);

if (cv->cv_len >= cv->cv_tot_len)
{
void *pd_sav = cv->cv_pdata;
cv->cv_tot_len <<= EXPANED_VAL;
cv->cv_pdata = realloc(cv->cv_pdata, cv->cv_tot_len * cv->cv_size);

if (!cv->cv_pdata)
{
cv->cv_pdata = pd_sav;
cv->cv_tot_len >>= EXPANED_VAL;
return CVEINSERT;
}
}

cvmemove_foreward(cv, iter, (char *)cv->cv_pdata + cv->cv_len * cv->cv_size);
memcpy(iter, memb, cv->cv_size);
cv->cv_len++;

return CVESUCCESS;
}

int cvector_insert_at(const cvector cv, size_t index, void *memb)
{
citerator iter;

if (index >= cv->cv_tot_len)
{
cv->cv_len = index + 1;
while (cv->cv_len >= cv->cv_tot_len) cv->cv_tot_len <<= EXPANED_VAL;
cv->cv_pdata = realloc(cv->cv_pdata, cv->cv_tot_len * cv->cv_size);
iter = (char *)cv->cv_pdata + cv->cv_size * index;
memcpy(iter, memb, cv->cv_size);
}
else
{
iter = (char *)cv->cv_pdata + cv->cv_size * index;
cvector_insert(cv, iter, memb);
}

return 0;
}

citerator cvector_next(const cvector cv, citerator iter)
{
return (char *)iter + cv->cv_size;
}

int cvector_val(const cvector cv, citerator iter, void *memb)
{
memcpy(memb, iter, cv->cv_size);
return 0;
}

int cvector_val_at(const cvector cv, size_t index, void *memb)
{
memcpy(memb, (char *)cv->cv_pdata + index * cv->cv_size, cv->cv_size);
return 0;
}

int cvector_rm(const cvector cv, citerator iter)
{
citerator from;
citerator end;
CWARNING_ITER(cv, iter, __FILE__, __func__, __LINE__);
from = iter;
end = cvector_end(cv);
memcpy(from, (char *)from + cv->cv_size, (char *)end - (char *)from);
cv->cv_len--;

if ((cv->cv_tot_len >= (MIN_LEN << REDUSED_VAL))
&& (cv->cv_len <= (cv->cv_tot_len >> REDUSED_VAL)))
{
void *pd_sav = cv->cv_pdata;
cv->cv_tot_len >>= EXPANED_VAL;
cv->cv_pdata = realloc(cv->cv_pdata, cv->cv_tot_len * cv->cv_size);

if (!cv->cv_pdata)
{
cv->cv_tot_len <<= EXPANED_VAL;
cv->cv_pdata = pd_sav;
return CVERM;
}
}

return CVESUCCESS;
}

int cvector_rm_at(const cvector cv, size_t index)
{
citerator iter;
iter = (char *)cv->cv_pdata + cv->cv_size * index;
CWARNING_ITER(cv, iter, __FILE__, __func__, __LINE__);
return cvector_rm(cv, iter);
}

void cv_info(const cvector cv)
{
printf("\n\ntot :%s : %d\n", __func__, cv->cv_tot_len);
printf("len :%s : %d\n", __func__, cv->cv_len);
printf("size:%s : %d\n\n", __func__, cv->cv_size);
return;
}

void cv_print(const cvector cv)
{
int num;
citerator iter;

if (cvector_length(cv) == 0)
fprintf(stderr, "file:%s func:%s line:%d error, null length cvector!!\n", __FILE__, __func__, __LINE__);

for (iter = cvector_begin(cv);
iter != cvector_end(cv);
iter = cvector_next(cv, iter))
{
cvector_iter_val(cv, iter, &num);
printf("var:%d at:%d\n", num, cvector_iter_at(cv, iter));
}

return;
}

//main.cpp
#include "cvector.h"

int main()
{
int i = 1;
cvector cv = cvector_create(sizeof(int));
cvector_pushback(cv, &i);
cvector_pushback(cv, &i);
cvector_pushback(cv, &i);
cvector_pushback(cv, &i);
cv_print(cv);
cvector_destroy(cv);
return 0;
}

————————————————
原文链接:https://blog.csdn.net/dengxu11/article/details/7311820

标签:__,cvector,iter,C语言,vector,len,改进版,cv,size
From: https://www.cnblogs.com/xihong2014/p/17063340.html

相关文章

  • 数据结构 C语言版 严蔚敏 电子书 pdf
    讲解的清楚、明白, 考研必备。关注公众号:后厂村搬砖工。发送:数据结构即可    ......
  • C语言实现扫雷游戏
    前言如何利用代码实现一个扫雷游戏呢?在我们玩过的扫雷游戏里,打开游戏后看到的是一个nxn的棋盘,我们需要点击棋盘的某一位置,在最短的时间内根据点击格子出现的数字找出所有非......
  • C语言实现三子棋游戏
    什么是三子棋游戏?三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,棋盘被占满前率先将自己的三个棋子......
  • LeetCode寻找两个正序数组的中位数(vector/二分查找 划分数组)
    原题解这道题可以转化成寻找两个有序数组中的第k小的数,其中k为(m+n)/2或(m+n)/2+1786.第k个数题目给定两个大小分别为m和n的正序(从小到大)数组nums1和nums2......
  • [数据结构] 栈 (C语言)
    栈栈的概念栈(stack)是一种特殊的线性表存储结构,其一端可以进行插入和弹出的操作,而另一端是封死的。可以把栈想象成是一个柱状的容器。就比如一个乒乓球筒,我们只能在筒的......
  • C语言概述
    一.C语言程序初识,先介绍一个简单的C语言程序:#include<stdio.h>intarr[100000];//声明一个较大的整型数组,尽量放在函数外部/*原因是:函数内部申请的局部变量空间,来自于......
  • C语言自加问题与整形提升
    提问:   在程序里,++a和+a在sizeof里,明显++a没有进行运算而+a进行运算并整形提升,这是为什么?解答: 这跟提升没有关系,这是运算优先级问题++a,运算优先级最高,所以是先进......
  • 如何使用C语言实现汉诺塔
    现有3个柱子A、B、C,有n个圆盘在A柱上,要实现n个圆盘要从A柱从大到小移动到C柱。思路:先将n-1个圆盘移动到B柱上,然后将最后一个圆盘移动到C柱上,最后将B柱上的n-1个圆盘移动到C......
  • c语言 打印数字金字塔
    提问: c语言。打印数字金字塔。for循环中为什么是j<i+1呢?以及如何判断这里的控制变量到底是与n有关还是与循环变量i有关呢?需要详细的解答 #include<stdio.h>voidpi......
  • c语言实现扫雷
    前言:上一篇博客我们写了三子棋小游戏,紧着这我们趁热打铁,继续巩固知识点,再来写一个更有意思的扫雷吧,想必扫雷大家都玩过,我就不做介绍了。概述:我们一样将代码分为三部分来写,主......