纪念逝去的岁月——C++实现一个栈(使用类模板)

这个版本是上个版本的加强版,上个版本的代码:http://www.cnblogs.com/fengbohello/p/4542912.html


目录

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 栈类的声明

//定义模版类 ClsStack
template<typename T> 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<typename T> ClsStack<T>::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<typename T> ClsStack<T>::~ClsStack()
{
    if(NULL != __m_Data)
    {
        delete __m_Data;
        __m_Data = NULL;
    }
    __m_pos = -1;
    __m_memsize = 0;
}

1.5)内存控制函数

//计算新的内存空间
//当参数是0的时候,指定内存空间是1
//参数不是0的时候,内存加倍
template<typename T> int ClsStack<T>::__doublesize(int n)
{
    int x = 0;
    if(0 == n)
    {
        x = 1;
    }
    else
    {
        x = n * 2;
    }

    return x;
}

//重新设定栈的大小
//就是扩展当前的内存容量到指定的大小
template<typename T> int ClsStack<T>::__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 faildn");
            delete p;
            return -1;
        }
        //printStack(p, __m_pos);
        delete __m_Data;
    }
    __m_Data = p;
    __m_memsize = n;

    return 0;
}

1.6)栈操作函数的实现

//弹出数据
//数据通过参数指定的指针返回
template<typename T> int ClsStack<T>::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<typename T> int ClsStack<T>::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<typename T> int ClsStack<T>::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<typename T> int ClsStack<T>::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<typename T> void ClsStack<T>::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("33[0;32m[SUCCESS %5d]33[0mn", __LINE__);
        }
        else
        {
            printf("33[0;31m[FAILD   %5d]33[0mn", __LINE__);
        }
    }while(0)

int main()
{
    ClsStack<int> 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 == NULLn");
            continue;
        }
        //测试弹出的数据和压入的数据是否一致
        TEST_EQ(i, *z);
        delete z;
    }
    int * g = NULL;
    objStack.pop(&g);
    TEST_EQ(x, *g);
}

完整代码如下(折叠了) :
纪念逝去的岁月——C++实现一个栈(使用类模板)纪念逝去的岁月——C++实现一个栈(使用类模板)

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 <stdio.h>
 19 #include <string.h>
 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<typename T> 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<typename T> ClsStack<T>::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<typename T> ClsStack<T>::~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的时候,指定内存空间是1
107 //参数不是0的时候,内存加倍
108 template<typename T> int ClsStack<T>::__doublesize(int n)
109 {
110     int x = 0;
111     if(0 == n)
112     {
113         x = 1;
114     }
115     else
116     {
117         x = n * 2;
118     }
119 
120     return x;
121 }
122 
123 //重新设定栈的大小
124 //就是扩展当前的内存容量到指定的大小
125 template<typename T> int ClsStack<T>::__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 faildn");
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<typename T> int ClsStack<T>::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     else
166     {
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<typename T> int ClsStack<T>::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     else
189     {
190         *ppData = __m_Data[__m_pos];
191         r = 0;
192     }
193 
194     return r;
195 }
196 
197 //向栈压入元素
198 //栈会自己判断内存,如果内存不足会自动增加内存
199 template<typename T> int ClsStack<T>::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<typename T> int ClsStack<T>::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<typename T> void ClsStack<T>::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("33[0;32m[SUCCESS %5d]33[0mn", __LINE__);
255         }
256         else
257         {
258             printf("33[0;31m[FAILD   %5d]33[0mn", __LINE__);
259         }
260     }while(0)
261 
262 int main()
263 {
264     ClsStack<int> 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 == NULLn");
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]

本文同步发表于博客园:http://www.cnblogs.com/fengbohello/p/4547598.html

作者: 风波

mail: fengbohello@foxmail.com
原文链接: https://www.cnblogs.com/fengbohello/p/4547598.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/217082

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午9:37
下一篇 2023年2月13日 上午9:37

相关推荐