对于头文件的解释也都以注释的形式写在了代码的注释里面,具体的头文件内容如下:
stack.h
#ifndef __sd_stack_h#define __sd_stack_h/*** @file stack.h @ingroup sd** @brief Generic stack object.** @todo documentation* @todo API homogeneity with sd_list and sd_hash*/#include <stddef.h>#include "defs.h"__SD_BEGIN_DECLS//栈的结构体类型,具体的结构体定义在c文件中typedef struct __sd_stack sd_stack_t;//创建一个栈结构,参数是这个栈的容量extern sd_stack_t* sd_stack_new(size_t max);//删除一个栈结构,参数是栈的名字和释放接口extern void sd_stack_delete(sd_stack_t* astack, void (*free_data_fn)(void *));//获得栈中当前有多少元素,参数为要查看的栈extern size_t sd_stack_get_nelem(const sd_stack_t* astack);//清空栈,参数为待清空的栈和释放接口extern void sd_stack_clear(sd_stack_t* astack, void (*free_data_fn)(void *));//入栈操作,参数为栈和待入栈的数据指针extern int sd_stack_push(sd_stack_t* astack, void *data);//出栈操作,参数为栈,返回值为出栈的数据extern void* sd_stack_pop(sd_stack_t* astack);//获得参数传入的栈的第一个位置的元素extern void* sd_stack_begin(sd_stack_t* astack);//获取参数传入栈的下一个位置的元素内容extern void* sd_stack_next(sd_stack_t* astack);//获取参数传入栈的最后一个位置的元素内容extern void* sd_stack_end(sd_stack_t* astack);//获得参数传入栈的栈顶元素extern void* sd_stack_peek(sd_stack_t* astack);__SD_END_DECLS#endif
里面同样有defs的一套东西,之前error里已经说过了。
接下来就是stack的实现:
#include <stdlib.h>#include <limits.h>#include <assert.h>#include "malloc.h"#include "stack.h"#define SD_STACK_INIT_SIZE 32struct __sd_stack {size_t max; //栈内元素最大个数,即栈容量size_t sp; //当前栈顶size_t size; //当前栈中设置的数量size_t iter; //栈内元素偏移指针void **array;};
以上是头文件包含和栈的结构体定义。具体都在里面进行了注释
sd_stack_new:
sd_stack_t* sd_stack_new(size_t max){sd_stack_t* this;//申请一个栈,大小为栈的结构体this = sd_calloc(1, sizeof(sd_stack_t));//栈的容量、元素大小、当前栈顶位置this->max = max == 0 ? INT_MAX : max;this->size = SD_STACK_INIT_SIZE;this->sp = 0;//申请参数传递的数量个栈元素,申请内存类型为void *this->array = sd_calloc(this->size, sizeof(*this->array));return this;}
sd_stack_delete:
void sd_stack_delete(sd_stack_t* this, void (*free_data_fn)(void *)){//参数有效性判断if (!this)return;//调用清除接口sd_stack_clear(this, free_data_fn);//释放内存free(this->array);free(this);}
调用的清除内存接口实现如下:
sd_stack_clear:
void sd_stack_clear(sd_stack_t* this, void (*free_data_fn)(void *)){if (!this)return;//逐个释放栈元素所指向的内存if (free_data_fn) {while (this->sp > 0) {free_data_fn(this->array[--(this->sp)]);}}}
sd_stack_get_nelem:
size_t sd_stack_get_nelem(const sd_stack_t* this){return this ? this->sp : -1;}
sd_stack_begin:
void* sd_stack_begin(sd_stack_t* this){if (!this)return NULL;//元素数组偏移设置为0后进行返回this->iter = 0;return this->array[this->iter];}
sd_stack_next:
void* sd_stack_next(sd_stack_t* this){//判断栈有效,并且当前iter偏移不高于sp返回iter的元素值if (this && this->iter < this->sp)return this->array[this->iter++];return NULL;}
sd_stack_end:
void* sd_stack_end(sd_stack_t* this){return sd_stack_peek(this);}
里面借用的sd_stack_peek的接口,实现如下
sd_stack_peek:
void* sd_stack_peek(sd_stack_t* this){if (!this || !this->sp)return NULL;//返回栈顶元素return this->array[this->sp - 1];}
sd_stack_push:
int sd_stack_push(sd_stack_t* this, void *data){if (this == NULL)return -1;//当前入栈个数已经达到了设置的数量,扩充if (this->sp == this->size){size_t new_size;//是否达到了最大数量if (this->size == this->max)return -1;//设置为最大数量或者为当前数量的二倍if (this->size * 2 > this->max) {new_size = this->max;} else {new_size = this->size * 2;}//重新进行元素栈内存的分配,realloc呵呵this->size = new_size;this->array = sd_realloc(this->array, sizeof(*this->array) * this->size);}//正确性验证assert(this->sp <= this->size);//入栈this->array[this->sp++] = data;return 0;}
sd_stack_pop:
void* sd_stack_pop(sd_stack_t* this){if (this == NULL || this->sp == 0)return NULL;//判断栈不为空且栈中数量可以进行缩减。其实不建议这么搞if (this->size >= SD_STACK_INIT_SIZE * 4 && this->sp < this->size / 4) {size_t new_size = this->size / 2;this->size = new_size;this->array = sd_realloc(this->array, sizeof(*this->array) * this->size);}//验证数据并进行出栈操作assert(this->sp > 0 && this->sp <= this->size);return this->array[--(this->sp)];}
比较简单明了的实现。