中科因仑“3+1”工程特种兵精英论坛
标题:
C语言通用模式编程--栈的实现
[打印本页]
作者:
emper
时间:
2016-3-29 17:54
标题:
C语言通用模式编程--栈的实现
最近在做XML解析器,中间需要用到二叉树,堆栈,所以写了一些通用算法
堆栈:支持任意数据类型的进栈和出栈(完成)
树:支持存储任意数据,支持任意节点的插入和删除操作(暂未完成)
先把通用栈代码给大家看看,欢迎使用,欢迎提意见
在不提供说明和例子,仅看头文件的话,我想大家用起来这个Stack,应该是没问题的^_^
============================== Header File =======================================
//******************************************************************************
//!
//! \file Stack.h
//! \brief Genernal Stack Model Interface.
//! You can use uniform stack API to manager different type of data
//! element.
//! \author cedar
//! \date 2013-11-22
//!
//! \license
//!
//! Copyright (c) 2013 Cedar MIT License
//!
//! Permission is hereby granted, free of charge, to any person obtaining a copy
//! of this software and associated documentation files (the "Software"), to deal
//! in the Software without restriction, including without limitation the rights to
//! use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
//! the Software, and to permit persons to whom the Software is furnished to do so,
//! subject to the following conditions:
//!
//! The above copyright notice and this permission notice shall be included in all
//! copies or substantial portions of the Software.
//!
//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
//! IN THE SOFTWARE.
///
//******************************************************************************
#ifndef __STACK_H__
#define __STACK_H__
#ifdef __cplusplus
extern "C"
{
#endif
//******************************************************************************
//! CONFIGURE MACRO
//******************************************************************************
#define SYS_INTXX_T //!< Use stdint standard datatype
#define USE_MEMORY_ALLOC //!< Use system malloc/free function
#include <stdio.h>
#ifdef SYS_INTXX_T
#include <stdint.h>
#else
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
#endif
#ifdef USE_MEMORY_ALLOC
#include <stdlib.h>
#endif
//******************************************************************************
//! PUBLIC TYPE
//******************************************************************************
//! Stack Memory Model
typedef struct Stack_t
{
uint8_t* pBaseAddr; //!< Stack Base Address
uint8_t* pEndAddr; //!< Stack Top Address
uint8_t* pIndex; //!< Stack Data Index Pointer
uint32_t UnitSize; //!< Statck Element Size(Unit: Byte)
}Stack_t;
//******************************************************************************
//! PUBLIC API
//******************************************************************************
#ifdef USE_MEMORY_ALLOC
extern Stack_t* Stack_Create(uint32_t StackSize, uint32_t UnitSize);
extern void Stack_Destory(Stack_t* pStack);
#endif // USE_MEMORY_ALLOC
extern int Stack_Init(Stack_t* pStack, void* pStackBaseAddr, uint32_t StackSize,
uint32_t UnitSize);
extern int Stack_Pop(Stack_t* pStack, void* pElement);
extern int Stack_Push(Stack_t* pStack, void* pElement);
#ifdef __cplusplus
}
#endif
#endif // __STACK_H__
[color=rgb(51, 102, 153) !important]复制代码
============================== Source Code =======================================
#include "Stack.h"
#ifdef USE_MEMORY_ALLOC
//******************************************************************************************
//
//! \brief Create An New Stack.
//!
//! \param [in] StackSize is the size of stack.
//! \param [in] UnitSize is the size of base element.
//! \retval The Pointer of new create stack.
//! \note -# If StackSize <= UnitSize or memory allocate failure, this function will return
//! with NULL pointer, So, Caller must check return pointer carefully.
//!
//! \note -# You must enable USE_MEMORY_ALLOC macro and ensure your system have <stdlib.h>
//! Header file before use this function.
//******************************************************************************************
Stack_t* Stack_Create(uint32_t StackSize, uint32_t UnitSize)
{
Stack_t* pStack = NULL; //!< Stack Pointer
uint8_t* pStackBaseAddr = NULL; //!< Stack Memory Base Address
//! Check stack parameters.
if(StackSize <= UnitSize)
{
//! Error, exit now.
return (NULL);
}
//! Allocate Memory for pointer of new stack.
pStack = (Stack_t*) malloc(sizeof(Stack_t));
if(NULL == pStack)
{
//! Allocate Failure, exit now.
return (NULL);
}
//! Allocate memory for stack.
pStackBaseAddr = malloc(StackSize);
if(NULL == pStackBaseAddr)
{
//! Allocate Failure, exit now.
return (NULL);
}
//! Initialize General Stack.
Stack_Init(pStack, pStackBaseAddr, StackSize, UnitSize);
return (pStack);
}
//******************************************************************************************
//
//! \brief Destory Stack
//! This function first release memory section, then reinit the stack pointer parameter.
//!
//! \param [in] pStack is the pointer of valid stack.
//! \retval None.
//!
//! \note -# You must enable USE_MEMORY_ALLOC macro and ensure your system have <stdlib.h>
//! Header file before use this function.
//
//******************************************************************************************
void Stack_Destory(Stack_t* pStack)
{
//! Check stack parameters.
if(NULL == pStack || NULL == pStack->pBaseAddr)
{
return; //!< Failure
}
//! Free stack memory
free(pStack->pBaseAddr);
//! Reset stack parameters
pStack->pBaseAddr = NULL;
pStack->pEndAddr = NULL;
pStack->pIndex = NULL;
pStack->UnitSize = NULL;
return; //!< Success
}
#endif // USE_MEMORY_ALLOC
//******************************************************************************************
//
//! \brief Initialize an exist stack.
//!
//! \param [in] pStack is the pointer of valid stack.
//! \param [in] pStackBaseAddr is the base address pre-alloc memory, such as array.
//! \param [in] StackSize is the size of stack.
//! \param [in] UnitSize is the size of base element.
//! \retval 0 if initialize successfully, otherwise return -1.
//!
//! \note -# If stack pointer invalid or memory allocate failure, this function will return
//! with NULL pointer, So, Caller must check return pointer carefully.
//!
//******************************************************************************************
int Stack_Init(Stack_t* pStack, void* pStackBaseAddr, uint32_t StackSize, uint32_t UnitSize)
{
//! Check stack parameters.
if(NULL == pStack || NULL == pStackBaseAddr || StackSize <= UnitSize)
{
//! Error, exit now.
return (-1);
}
//! Success, Initilize stack
pStack->pBaseAddr = (uint8_t*) pStackBaseAddr;
pStack->pEndAddr = (uint8_t*) ((uint32_t)pStackBaseAddr + StackSize);
pStack->pIndex = (uint8_t*) pStackBaseAddr;
pStack->UnitSize = UnitSize;
return (0);
}
//******************************************************************************************
//
//! \brief Pop an element from stack.
//!
//! \param [in] pStack is the pointer of valid stack.
//! \param [out] pElement is the address of memory that store the pop element.
//!
//! \retval 0 if initialize successfully, otherwise return -1.
//
//******************************************************************************************
int Stack_Pop(Stack_t* pStack, void* pElement)
{
uint8_t * _pElement = (uint8_t *)pElement;
int i = 0;
//! Check stack parameters.
if(NULL == pStack || NULL == pElement)
{
//! Error, exit now.
return (-1);
}
//! UnderFlow ?
if(pStack->pIndex < pStack->pBaseAddr + pStack->UnitSize)
{
//! Error, Stack is empty!
return (-1);
}
//! Move Stack Pointer
pStack->pIndex = pStack->pIndex - pStack->UnitSize;
//! Copy Data
for(i = 0; i < pStack->UnitSize; i++)
{
*_pElement++ = *(pStack->pIndex + i);
}
return (0);
}
//******************************************************************************************
//
//! \brief Push an element into stack.
//!
//! \param [in] pStack is the pointer of valid stack.
//! \param [in] pElement is data element you want to push.
//!
//! \retval 0 if initialize successfully, otherwise return -1.
//
//******************************************************************************************
int Stack_Push(Stack_t* pStack, void* pElement)
{
uint8_t * _pElement = (uint8_t *)pElement;
int i = 0;
//! Check stack parameters.
if(NULL == pStack || NULL == pElement)
{
//! Error, exit now.
return (-1);
}
//! Overflow ?
if(pStack->pIndex + pStack->UnitSize > pStack->pEndAddr)
{
return (-1);
}
//! Copy Data
for(i = 0; i < pStack->UnitSize; i++)
{
*(pStack->pIndex++) = *_pElement++;
}
return (0);
}
[color=rgb(51, 102, 153) !important]复制代码
注:
1: 最新代码,请参考
https://github.com/cedar-renjun/General_Programming_Stack/
2: BinTree在进行中,会分享给大家
欢迎光临 中科因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/)
Powered by Discuz! X3.4