博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
纪念逝去的岁月——C++实现一个栈(使用类模板)
阅读量:5339 次
发布时间:2019-06-15

本文共 11036 字,大约阅读时间需要 36 分钟。

这个版本是上个版本的加强版,上个版本的代码:


 目录

1、代码

2、运行结果


 1、代码

1.1 调试信息的配置

//一个调试开关,如果要看调试信息,就把这个开关的注释去掉//#define USEDEBUG//如果调试开关打开了,就定义好调试的输出函数(其实是个宏),#ifdef USEDEBUG#define DEBUG(fmt, arg...)\    do{\        printf("%s %d %s() : ", __FILE__, __LINE__, __func__);\        printf(fmt, ##arg);\    }while(0)#else//如果没有打开,这个函数什么也不做#define DEBUG(fmt, arg...)#endif

1.2 栈类的声明

//定义模版类 ClsStacktemplate
class ClsStack{ //这个类的=型私有数据,主要用于对栈的内存分配进行管理, //用户不需要关心内存,只需要调用对外提供的几个方法就可以了 private : T ** __m_Data;//存储数据的内存开始地址 int __m_pos;//记录栈尾的位置,插入数据时插入这个位置 int __m_memsize;//记录内存的总数 protected : //重新分配内存空间,可以减小,也可以增大 int __resize(int n); //获取给定参数的双倍内存,其实主要目的是防止参数是0 int __doublesize(int n); public : ClsStack(int n = 0); ~ClsStack(); //弹出栈顶 int pop (T ** ppData); //获取栈顶元素,但是不弹出 int top (T ** ppData); //向栈添加数据 int push(T * pData); //清空整个栈的数据 int clear(void (*)(T*)); //输出整个栈的数据,用于调试 void printStack(T * p[], int pos);};

1.3 构造函数的实现

//构造函数//默认参数值是0//参数非零时的作用是用于初始化栈空间的大小template
ClsStack
::ClsStack(int n){ __m_Data = NULL; __m_pos = -1; __m_memsize = 0; if(0 != n) { __m_Data = new T * [n]; if(NULL != __m_Data) { __m_memsize = n; } }}

1.4) 析构函数的实现

//析构函数//在栈对象被销毁时,需要把申请的内存空间释放template
ClsStack
::~ClsStack(){ if(NULL != __m_Data) { delete __m_Data; __m_Data = NULL; } __m_pos = -1; __m_memsize = 0;}

1.5)内存控制函数

//计算新的内存空间//当参数是0的时候,指定内存空间是1//参数不是0的时候,内存加倍template
int ClsStack
::__doublesize(int n){ int x = 0; if(0 == n) { x = 1; } else { x = n * 2; } return x;}//重新设定栈的大小//就是扩展当前的内存容量到指定的大小template
int ClsStack
::__resize(int n){ T ** p = new T * [n]; if(NULL == p) { return -1; } memset(p, 0, sizeof(T *) * (n)); if(NULL != __m_Data) { //printStack(__m_Data, __m_pos); if( NULL == memcpy(p, __m_Data, __m_memsize * sizeof(T *))) { DEBUG("memcpy faild\n"); delete p; return -1; } //printStack(p, __m_pos); delete __m_Data; } __m_Data = p; __m_memsize = n; return 0;}

1.6)栈操作函数的实现

//弹出数据//数据通过参数指定的指针返回template
int ClsStack
::pop(T ** ppData){ if(NULL == ppData) { return -1; } int r = 0; if(-1 == __m_pos) { *ppData = NULL; r = -1; } else { *ppData = __m_Data[__m_pos --]; r = 0; DEBUG("memsize : [%u], pos : [%d], p = [0X%08X]\n", __m_memsize, __m_pos + 1, (unsigned int)*ppData); } return r;}//获取栈顶元素,并不弹出template
int ClsStack
::top(T ** ppData){ if(NULL == ppData) { return -1; } int r = 0; if(-1 == __m_pos) { *ppData = NULL; r = -1; } else { *ppData = __m_Data[__m_pos]; r = 0; } return r;}//向栈压入元素//栈会自己判断内存,如果内存不足会自动增加内存template
int ClsStack
::push(T * pData){ if(__m_pos + 1 >= __m_memsize) { int n = __doublesize(__m_memsize); if(0 != __resize(n)) { return -1; } } __m_Data[++__m_pos] = pData; DEBUG("memsize : [%u], pos : [%d], p = [0X%08X]\n", __m_memsize, __m_pos, (unsigned int)__m_Data[__m_pos]); return 0;}

1.7)清空栈数据函数

//清空栈,需要指定回收元素数据的函数,//否则无法知道如何回收由用户申请的内存空间template
int ClsStack
::clear(void (*F)(T *)){ if(NULL == F && __m_pos >= 0) { return -1; } if(NULL != __m_Data && 0 != __m_memsize) { for(int i = 0; i <= __m_pos; i++) { F(__m_Data[i]); __m_Data[i] = NULL; } delete __m_Data; } __m_Data = NULL; __m_pos = -1; __m_memsize = 0;}

1.8)调试辅助函数

//输出栈的内存状态,调试时使用template
void ClsStack
::printStack(T * p[], int pos){ int i = 0; for(i = 0; i <= pos; i++) { printf("[%08u] = [0X%08X]\n", i, NULL == p ? 0 : p[i]); } printf("----------------------------\n");}

1.9)测试代码

//test 函数定义#define TEST_EQ(a, b)\    do{\        if(a == b)\        {\            printf("\033[0;32m[SUCCESS %5d]\033[0m\n", __LINE__);\        }\        else\        {\            printf("\033[0;31m[FAILD   %5d]\033[0m\n", __LINE__);\        }\    }while(0)int main(){    ClsStack
objStack; int x = 10; int * p = &x; //向栈内压入数据 objStack.push(p); int i = 0; for(i = 0; i <= 10; i++) { int * z = new int; *z = i; objStack.push(z); } //开始弹出数据 for(i = 10; i >= 0; i--) { int * z = NULL; objStack.pop(&z); if(NULL == z) { printf("z == NULL\n"); continue; } //测试弹出的数据和压入的数据是否一致 TEST_EQ(i, *z); delete z; } int * g = NULL; objStack.pop(&g); TEST_EQ(x, *g);}

 

完整代码如下(折叠了) :

1 /*  2  * =====================================================================================  3  *  4  *       Filename:  stack.cpp  5  *  6  *    Description:  a template stack library  7  *  8  *        Version:  1.0  9  *        Created:  10/13/2016 09:52:46 AM 10  *       Revision:  none 11  *       Compiler:  gcc 12  * 13  *         Author:  YOUR NAME (fengbohello@foxmail.com),  14  *   Organization:   15  * 16  * ===================================================================================== 17  */ 18 #include 
19 #include
20 21 //一个调试开关,如果要看调试信息,就把这个开关的注释去掉 22 //#define USEDEBUG 23 24 //如果调试开关打开了,就定义好调试的输出函数(其实是个宏), 25 #ifdef USEDEBUG 26 #define DEBUG(fmt, arg...)\ 27 do{\ 28 printf("%s %d %s() : ", __FILE__, __LINE__, __func__);\ 29 printf(fmt, ##arg);\ 30 }while(0) 31 #else 32 //如果没有打开,这个函数什么也不做 33 #define DEBUG(fmt, arg...) 34 #endif 35 36 //定义模版类 ClsStack 37 template
class ClsStack 38 { 39 //这个类的=型私有数据,主要用于对栈的内存分配进行管理, 40 //用户不需要关心内存,只需要调用对外提供的几个方法就可以了 41 private : 42 T ** __m_Data;//存储数据的内存开始地址 43 int __m_pos;//记录栈尾的位置,插入数据时插入这个位置 44 int __m_memsize;//记录内存的总数 45 46 protected : 47 //重新分配内存空间,可以减小,也可以增大 48 int __resize(int n); 49 50 //获取给定参数的双倍内存,其实主要目的是防止参数是0 51 int __doublesize(int n); 52 53 public : 54 ClsStack(int n = 0); 55 ~ClsStack(); 56 57 //弹出栈顶 58 int pop (T ** ppData); 59 60 //获取栈顶元素,但是不弹出 61 int top (T ** ppData); 62 63 //向栈添加数据 64 int push(T * pData); 65 66 //清空整个栈的数据 67 int clear(void (*)(T*)); 68 69 //输出整个栈的数据,用于调试 70 void printStack(T * p[], int pos); 71 }; 72 73 //构造函数 74 //默认参数值是0 75 //参数非零时的作用是用于初始化栈空间的大小 76 template
ClsStack
::ClsStack(int n) 77 { 78 __m_Data = NULL; 79 __m_pos = -1; 80 __m_memsize = 0; 81 82 if(0 != n) 83 { 84 __m_Data = new T * [n]; 85 if(NULL != __m_Data) 86 { 87 __m_memsize = n; 88 } 89 } 90 } 91 92 //析构函数 93 //在栈对象被销毁时,需要把申请的内存空间释放 94 template
ClsStack
::~ClsStack() 95 { 96 if(NULL != __m_Data) 97 { 98 delete __m_Data; 99 __m_Data = NULL;100 }101 __m_pos = -1;102 __m_memsize = 0;103 }104 105 //计算新的内存空间106 //当参数是0的时候,指定内存空间是1107 //参数不是0的时候,内存加倍108 template
int ClsStack
::__doublesize(int n)109 {110 int x = 0;111 if(0 == n)112 {113 x = 1;114 }115 else116 {117 x = n * 2;118 }119 120 return x;121 }122 123 //重新设定栈的大小124 //就是扩展当前的内存容量到指定的大小125 template
int ClsStack
::__resize(int n)126 {127 T ** p = new T * [n];128 if(NULL == p)129 {130 return -1;131 }132 memset(p, 0, sizeof(T *) * (n));133 if(NULL != __m_Data)134 {135 //printStack(__m_Data, __m_pos);136 if( NULL == memcpy(p, __m_Data, __m_memsize * sizeof(T *)))137 {138 DEBUG("memcpy faild\n");139 delete p;140 return -1;141 }142 //printStack(p, __m_pos);143 delete __m_Data;144 }145 __m_Data = p;146 __m_memsize = n;147 148 return 0;149 }150 151 //弹出数据152 //数据通过参数指定的指针返回153 template
int ClsStack
::pop(T ** ppData)154 {155 if(NULL == ppData)156 {157 return -1;158 }159 int r = 0;160 if(-1 == __m_pos)161 {162 *ppData = NULL;163 r = -1;164 }165 else166 {167 *ppData = __m_Data[__m_pos --];168 r = 0;169 DEBUG("memsize : [%u], pos : [%d], p = [0X%08X]\n", __m_memsize, __m_pos + 1, (unsigned int)*ppData);170 }171 172 return r;173 }174 175 //获取栈顶元素,并不弹出176 template
int ClsStack
::top(T ** ppData)177 {178 if(NULL == ppData)179 {180 return -1;181 }182 int r = 0;183 if(-1 == __m_pos)184 {185 *ppData = NULL;186 r = -1;187 }188 else189 {190 *ppData = __m_Data[__m_pos];191 r = 0;192 }193 194 return r;195 }196 197 //向栈压入元素198 //栈会自己判断内存,如果内存不足会自动增加内存199 template
int ClsStack
::push(T * pData)200 {201 if(__m_pos + 1 >= __m_memsize)202 {203 int n = __doublesize(__m_memsize);204 if(0 != __resize(n))205 {206 return -1;207 }208 }209 __m_Data[++__m_pos] = pData;210 DEBUG("memsize : [%u], pos : [%d], p = [0X%08X]\n", __m_memsize, __m_pos, (unsigned int)__m_Data[__m_pos]);211 212 return 0;213 }214 215 //清空栈,需要指定回收元素数据的函数,216 //否则无法知道如何回收由用户申请的内存空间217 template
int ClsStack
::clear(void (*F)(T *))218 {219 if(NULL == F && __m_pos >= 0)220 {221 return -1;222 }223 if(NULL != __m_Data && 0 != __m_memsize)224 {225 for(int i = 0; i <= __m_pos; i++)226 {227 F(__m_Data[i]);228 __m_Data[i] = NULL;229 }230 delete __m_Data;231 }232 __m_Data = NULL;233 __m_pos = -1;234 __m_memsize = 0;235 }236 237 //输出栈的内存状态,调试时使用238 template
void ClsStack
::printStack(T * p[], int pos)239 {240 int i = 0;241 for(i = 0; i <= pos; i++)242 {243 printf("[%08u] = [0X%08X]\n", i, NULL == p ? 0 : p[i]);244 }245 printf("----------------------------\n");246 }247 248 249 //test 函数定义250 #define TEST_EQ(a, b)\251 do{\252 if(a == b)\253 {\254 printf("\033[0;32m[SUCCESS %5d]\033[0m\n", __LINE__);\255 }\256 else\257 {\258 printf("\033[0;31m[FAILD %5d]\033[0m\n", __LINE__);\259 }\260 }while(0)261 262 int main()263 {264 ClsStack
objStack;265 int x = 10;266 int * p = &x;267 268 //向栈内压入数据269 objStack.push(p);270 int i = 0;271 for(i = 0; i <= 10; i++)272 {273 int * z = new int;274 *z = i;275 objStack.push(z);276 }277 //开始弹出数据278 for(i = 10; i >= 0; i--)279 {280 int * z = NULL;281 objStack.pop(&z);282 if(NULL == z)283 {284 printf("z == NULL\n");285 continue;286 }287 //测试弹出的数据和压入的数据是否一致288 TEST_EQ(i, *z);289 delete z;290 }291 int * g = NULL;292 objStack.pop(&g);293 TEST_EQ(x, *g);294 }
View Code

 


2、运行结果

  2.1、编译

g++ -g  -c -o stack.o stack.cpp -Wall -I./g++ -g  -o stack stack.o -Wall -I./

 

  2.2、运行结果

$ ./stack [SUCCESS   288][SUCCESS   288][SUCCESS   288][SUCCESS   288][SUCCESS   288][SUCCESS   288][SUCCESS   288][SUCCESS   288][SUCCESS   288][SUCCESS   288][SUCCESS   288][SUCCESS   293]

  


本文同步发表于博客园:

作者: 风波

mail: fengbohello@foxmail.com

转载于:https://www.cnblogs.com/fengbohello/p/4547598.html

你可能感兴趣的文章
关于python中带下划线的变量和函数 的意义
查看>>
linux清空日志文件内容 (转)
查看>>
安卓第十三天笔记-服务(Service)
查看>>
Servlet接收JSP参数乱码问题解决办法
查看>>
【bzoj5016】[Snoi2017]一个简单的询问 莫队算法
查看>>
Ajax : load()
查看>>
MySQL-EXPLAIN执行计划Extra解释
查看>>
Zookeeper概述
查看>>
Zookeeper一致性级别
查看>>
Linux远程登录
查看>>
Linux自己安装redis扩展
查看>>
HDU 1016 Prime Ring Problem(dfs)
查看>>
C#中结构体与字节流互相转换
查看>>
session和xsrf
查看>>
跟随大神实现简单的Vue框架
查看>>
Linux目录结构
查看>>
LeetCode-Strobogrammatic Number
查看>>
luoguP3414 SAC#1 - 组合数
查看>>
五一 DAY 4
查看>>
(转)接口测试用例设计(详细干货)
查看>>