一、思考

  最开始写的栈,通过宏来改变元素数据类型,在同一程序中只能用于一种数据类型,想要用于多种数据类型则要复制代码并改名。那么,有没有方法不复制代码就可以用于多种数据类型?

二、基本思路

  在我的经验中,栈内的数据不参与运算,对元素的操作只有两种——流入和流出栈。也就是说,数据类型不重要,只要做到正确流入流出即可。(void*)

三、栈的源码

  共2个文件,x_sq_stack.h、x_sq_stack.c。莫纠结前缀x,与代码无任何关系。

 /*************************************************************
* x_sq_stack.h
*
* 固定大小的栈,顺序存储
* 把需要的数据类型重命名为s_elemtype即可
*
* **********************************************************/ #ifndef X_SQ_STACK_H
#define X_SQ_STACK_H #define OK 0 //pop()、push()函数成功返回
#define TRUE 1 //isnull()、isfull()
#define FALSE 0 //isnull()、isfull()
#define ERR_SQ_STACK_FULL 2 //栈满时push()函数返回
#define ERR_SQ_STACK_NULL 3 //栈空时pop()函数返回 typedef struct sq_stack{
void *base; //栈空间地址
int t_size; //元素大小(字节数)
int size; //栈大小
int top; //栈顶索引
}sq_stack; /***********************************************************
*
* 创建和销毁栈
*
* 参数:
* size 栈大小
* t_size 元素大小
*
* 返回:
* create_..() 不成功返回NULL
*
* ********************************************************/
struct sq_stack * create_sq_stack(int size, int t_size);
void free_sq_stack(struct sq_stack *s); /**********************************************************
*
* 入栈和出栈
* 成功都返回OK,不成功分别返回ERR_SQ_STACK_FULL、ERR_SQ_STACK_NULL
*
* ********************************************************/
int push_sq_stack(struct sq_stack *s, const void *data);
int pop_sq_stack(struct sq_stack *s, void *data); /**********************************************************
*
* 判断是否是满栈或空栈
* 成立返回TRUE,不成立返回FALSE
*
* ********************************************************/
int isfull_sq_stack(const struct sq_stack *s);
int isnull_sq_stack(const struct sq_stack *s); #endif /*X_SQ_STACK_H*/
 /* x_sq_stack.c */

 #include "x_sq_stack.h"
#include <string.h>
#include <stdlib.h> struct sq_stack * create_sq_stack(int size, int t_size)
{
struct sq_stack *s;
int mem_size = sizeof(struct sq_stack) + size*t_size;
if(!(s=(struct sq_stack *)malloc(mem_size))){
return NULL;
}
s->base = (void*)(s+);
s->size = size;
s->t_size = t_size;
s->top = -;
return s;
} void free_sq_stack(struct sq_stack *s)
{
free(s);
} int push_sq_stack(struct sq_stack *s, const void *data)
{
if(s->top < s->size-){
s->top ++;
memcpy(s->base + s->top * s->t_size, data, s->t_size);
return OK;
}else{
return ERR_SQ_STACK_FULL;
}
} int pop_sq_stack(struct sq_stack *s, void *data)
{
if(s->top >= ){
memcpy(data, s->base + s->top * s->t_size, s->t_size);
s->top --;
return OK;
}else{
return ERR_SQ_STACK_NULL;
}
} int isfull_sq_stack(const struct sq_stack *s)
{
if(s->top >= s->size-) return TRUE;
else return FALSE;
} int isnull_sq_stack(const struct sq_stack *s)
{
if(s->top < ) return TRUE;
else return FALSE;
}

四、测试

 /* main.c */

 #include "x_sq_stack.h"
#include <stdio.h> #define TYPE_1 long
#define TYPE_2 double int main(int argc, char *argv[])
{
sq_stack *s1,*s2; s1=create_sq_stack(,sizeof(TYPE_1));
s2=create_sq_stack(,sizeof(TYPE_2));
if(!s1 || !s2){
printf("内存分配失败!\n");
return ;
} double temp;
for(int i=; i<; i++){
if(push_sq_stack(s1,&i) == ERR_SQ_STACK_FULL){
printf("s1 栈已满!\n");
}
temp = i/2.1;
if(push_sq_stack(s2,&temp) == ERR_SQ_STACK_FULL){
printf("s2 栈已满!\n");
break;
}
} TYPE_1 a1; for(int i=; i<; i++){
if(pop_sq_stack(s1,&a1) != ERR_SQ_STACK_NULL){
printf("%d ",a1);
}else{
printf("\ns1 栈已空!\n");
break;
}
} TYPE_2 a2;
for(int i=; i<; i++){
if(pop_sq_stack(s2,&a2) != ERR_SQ_STACK_NULL){
printf("%lf ",a2);
}else{
printf("\ns2 栈已空!\n");
break;
}
} free_sq_stack(s1);
free_sq_stack(s2);
return ;
}

测试结果

C语言实现可复用栈的更多相关文章

  1. C语言中堆和栈的区别

    原文:http://blog.csdn.net/tigerjibo/article/details/7423728 C语言中堆和栈的区别 一.前言: C语言程序经过编译连接后形成编译.连接后形成的二进 ...

  2. C语言函数参数压栈顺序为何是从右到左?(从左向右的话,碰到printf的会陷入死循环)

    上学期学习了汇编语言,并在操作系统实验中使用了汇编+C语言混合编程,中间也了解了一些C语言与汇编语言的对应关系. 由于汇编语言是底层的编程语言,各种函数参数都要直接控制栈进行存取,在混合编程中,要用汇 ...

  3. C语言简单实现链栈基本几个功能(适合新手看,大神可指正)

            接着上一次的顺序栈,今天我记一下链栈,因为我也是刚学不久,有些地方也稍稍理解不了,所以,一起共勉.我会用我自己结合教材上画的图,争取跟代码一起结合,用文字和图最大化的解释代码,这样的话 ...

  4. [JZOJ3588]【中山市选2014】J语言(表达式解析+栈)

    Description J语言作为一门编程语言,诞生于20世纪90年代.............. 好学的小H今天又学到了一种新东西——J语言.显然,J语言的背景已经被小H忘得一干二净了,但是小H仍然 ...

  5. C语言简单实现链栈基本几个功能

            接着上一次的顺序栈,今天我记一下链栈,因为我也是刚学不久,有些地方也稍稍理解不了,所以,一起共勉.我会用我自己结合教材上画的图,争取跟代码一起结合,用文字和图最大化的解释代码,这样的话 ...

  6. c语言学习,模拟栈操作

    1.stack.c模拟栈操作函数的实现 #include<stdio.h> #include<stdlib.h> ; static char *stack;//数据栈 ;//栈 ...

  7. C++学习(三十二)(C语言部分)之 栈

    栈测试代码笔记如下: #include<stdio.h> #include<string.h> #include <stdlib.h> #define SIZE 1 ...

  8. C++学习(三十一)(C语言部分)之 栈和队列(括号匹配示例)

    括号匹配测试代码笔记如下: #include<stdio.h> #include<string.h> #include <stdlib.h> #define SIZ ...

  9. C++学习(三十)(C语言部分)之 栈和队列

    数据结构1.保存数据 2.处理数据数组+操作增查删改 栈和队列是一种操作受限的线性表 栈 是先进后出 是在一端进行插入删除的操作--->栈顶 另一端叫做栈底(栈和栈区是两个概念)(是一种数据结构 ...

随机推荐

  1. Linux学习---Linux安装ftp组件

    1 安装vsftpd组件 安装完后,有/etc/vsftpd/vsftpd.conf 文件,是vsftp的配置文件. [root@bogon ~]# yum -y install vsftpd 2 添 ...

  2. January 12 2017 Week 2 Thursday

    Although it rains, throw not away your watering pot. 纵然天下雨,休把水壶丢. Don't throw away your watering pot ...

  3. 两天学会css基础(二)

    接上一篇博客,还有css中的两个重要知识点没有说到,就是元素的浮动与定位. 第三部分:元素的浮动与清除 这部分的内容之前的博客已总结过.请查看css中的浮动与三种清除浮动的方法这篇文章. 浮动在网页中 ...

  4. Hadoop Spark 基础教程

    0x01  Hadoop 慕课网 https://www.imooc.com/learn/391 Hadoop基础 慕课网 https://www.imooc.com/learn/890 Hadoop ...

  5. 使用SN.exe对.Net生成的程序集进行签名

    CLR用数字签名的方式防止程序集发布后被人篡改,也可以确定发布人,这个方法就是使用公/私钥对,然后对程序集所有模块取一个哈希生成一个数字签名放在程序集的元数据中. 1.创建公/私钥对     创建公/ ...

  6. Git版本控制 备忘录

    安装Git: 在Linux上安装Git: sudo apt-get install git 在windows上安装Git: 从https://git-for-windows.github.io下载,然 ...

  7. BZOJ2223/3524:[POI2014] Couriers(主席树)

    Description 给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0 ...

  8. [19/04/28-星期日] GOF23_结构型模式(享元模式)

    一.享元模式(FlyWeight,轻量级) [共享类与非共享类] /*** *FlyweightFactory享元工厂类: 创建并管理享元对象,享元池一般设计成键值对 */ package cn.sx ...

  9. Codeforce Round #554 Div.2 D - Neko and Aki's Prank

    dp 找规律 我好菜啊好菜啊,完全没有思路. 在合法的括号序列中,左括号数一定大于等于右括号数的,所以我们可以先定义平衡度为左括号数-右括号数. 然后可以发现一个惊人的规律..就是在trie同一深度上 ...

  10. PAT——1042. 字符统计

    请编写程序,找出一段给定文字中出现最频繁的那个英文字母. 输入格式: 输入在一行中给出一个长度不超过1000的字符串.字符串由ASCII码表中任意可见字符及空格组成,至少包含1个英文字母,以回车结束( ...