C语言实现可复用栈
一、思考
最开始写的栈,通过宏来改变元素数据类型,在同一程序中只能用于一种数据类型,想要用于多种数据类型则要复制代码并改名。那么,有没有方法不复制代码就可以用于多种数据类型?
二、基本思路
在我的经验中,栈内的数据不参与运算,对元素的操作只有两种——流入和流出栈。也就是说,数据类型不重要,只要做到正确流入流出即可。(void*)
三、栈的源码
共2个文件,x_sq_stack.h、x_sq_stack.c。莫纠结前缀x,与代码无任何关系。
1 /************************************************************* 2 * x_sq_stack.h 3 * 4 * 固定大小的栈,顺序存储 5 * 把需要的数据类型重命名为s_elemtype即可 6 * 7 * **********************************************************/ 8 9 #ifndef X_SQ_STACK_H 10 #define X_SQ_STACK_H 11 12 #define OK 0 //pop()、push()函数成功返回 13 #define TRUE 1 //isnull()、isfull() 14 #define FALSE 0 //isnull()、isfull() 15 #define ERR_SQ_STACK_FULL 2 //栈满时push()函数返回 16 #define ERR_SQ_STACK_NULL 3 //栈空时pop()函数返回 17 18 typedef struct sq_stack{ 19 void *base; //栈空间地址 20 int t_size; //元素大小(字节数) 21 int size; //栈大小 22 int top; //栈顶索引 23 }sq_stack; 24 25 /*********************************************************** 26 * 27 * 创建和销毁栈 28 * 29 * 参数: 30 * size 栈大小 31 * t_size 元素大小 32 * 33 * 返回: 34 * create_..() 不成功返回NULL 35 * 36 * ********************************************************/ 37 struct sq_stack * create_sq_stack(int size, int t_size); 38 void free_sq_stack(struct sq_stack *s); 39 40 /********************************************************** 41 * 42 * 入栈和出栈 43 * 成功都返回OK,不成功分别返回ERR_SQ_STACK_FULL、ERR_SQ_STACK_NULL 44 * 45 * ********************************************************/ 46 int push_sq_stack(struct sq_stack *s, const void *data); 47 int pop_sq_stack(struct sq_stack *s, void *data); 48 49 /********************************************************** 50 * 51 * 判断是否是满栈或空栈 52 * 成立返回TRUE,不成立返回FALSE 53 * 54 * ********************************************************/ 55 int isfull_sq_stack(const struct sq_stack *s); 56 int isnull_sq_stack(const struct sq_stack *s); 57 58 59 #endif /*X_SQ_STACK_H*/
1 /* x_sq_stack.c */ 2 3 #include "x_sq_stack.h" 4 #include <string.h> 5 #include <stdlib.h> 6 7 8 struct sq_stack * create_sq_stack(int size, int t_size) 9 { 10 struct sq_stack *s; 11 int mem_size = sizeof(struct sq_stack) + size*t_size; 12 if(!(s=(struct sq_stack *)malloc(mem_size))){ 13 return NULL; 14 } 15 s->base = (void*)(s+1); 16 s->size = size; 17 s->t_size = t_size; 18 s->top = -1; 19 return s; 20 } 21 22 void free_sq_stack(struct sq_stack *s) 23 { 24 free(s); 25 } 26 27 int push_sq_stack(struct sq_stack *s, const void *data) 28 { 29 if(s->top < s->size-1){ 30 s->top ++; 31 memcpy(s->base + s->top * s->t_size, data, s->t_size); 32 return OK; 33 }else{ 34 return ERR_SQ_STACK_FULL; 35 } 36 } 37 38 int pop_sq_stack(struct sq_stack *s, void *data) 39 { 40 if(s->top >= 0){ 41 memcpy(data, s->base + s->top * s->t_size, s->t_size); 42 s->top --; 43 return OK; 44 }else{ 45 return ERR_SQ_STACK_NULL; 46 } 47 } 48 49 50 int isfull_sq_stack(const struct sq_stack *s) 51 { 52 if(s->top >= s->size-1) return TRUE; 53 else return FALSE; 54 } 55 56 int isnull_sq_stack(const struct sq_stack *s) 57 { 58 if(s->top < 0) return TRUE; 59 else return FALSE; 60 }
四、测试
1 /* main.c */ 2 3 #include "x_sq_stack.h" 4 #include <stdio.h> 5 6 #define TYPE_1 long 7 #define TYPE_2 double 8 9 int main(int argc, char *argv[]) 10 { 11 sq_stack *s1,*s2; 12 13 s1=create_sq_stack(10,sizeof(TYPE_1)); 14 s2=create_sq_stack(10,sizeof(TYPE_2)); 15 if(!s1 || !s2){ 16 printf("内存分配失败!\n"); 17 return 1; 18 } 19 20 double temp; 21 for(int i=0; i<20; i++){ 22 if(push_sq_stack(s1,&i) == ERR_SQ_STACK_FULL){ 23 printf("s1 栈已满!\n"); 24 } 25 temp = i/2.1; 26 if(push_sq_stack(s2,&temp) == ERR_SQ_STACK_FULL){ 27 printf("s2 栈已满!\n"); 28 break; 29 } 30 } 31 32 TYPE_1 a1; 33 34 for(int i=0; i<20; i++){ 35 if(pop_sq_stack(s1,&a1) != ERR_SQ_STACK_NULL){ 36 printf("%d ",a1); 37 }else{ 38 printf("\ns1 栈已空!\n"); 39 break; 40 } 41 } 42 43 TYPE_2 a2; 44 for(int i=0; i<20; i++){ 45 if(pop_sq_stack(s2,&a2) != ERR_SQ_STACK_NULL){ 46 printf("%lf ",a2); 47 }else{ 48 printf("\ns2 栈已空!\n"); 49 break; 50 } 51 } 52 53 free_sq_stack(s1); 54 free_sq_stack(s2); 55 return 0; 56 }
测试结果