⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stack.c

📁 国外网站上的一些精典的C程序
💻 C
字号:
/* =======================================================================    STACK.c     Stack manager.                A.Reitsma, Delft, Nederland.                v0.25  94-07-03  Public Domain.    Many times I wanted to have one or more stacks for the program I was    working on. Sometimes I did without -- especially on Quick and Dirty    utilities. At other times I cobbled up something that more or less    seemed to work. Crashes were common ...    So I decided to take the time to do something about it.    This is the result. -  The Stack system is based on dynamic arrays: automatically growing    the stacks when needed. The growing is done in steps of 16 items.    This reduces the number of required memory reallocations (and    therefore the number of allocation failures). -  Stack shrinking is intentionally not implemented. -  ItemSizes larger than 2kB are not supported: the minimum of initial    StackItems per stack is currently 32.    An assert (debug version) limits ItemSizes: <= 1kB and >= 2 Bytes.    For large data items a separate 'user' module is probably sensible.    StackUnpop is added to take a look at info, especially size info so    an appropriate amount of memory can be allocated by the user. -  A certain amount of redundancy is provided to enable integrity checks    for use in programs with 'wild pointer' problems. -  Compile with NDEBUG defined for a 'production' version.    Compile with NDEBUG _not_ defined for a debug version. -  Some functions benefit by using the compilers optimizer.    Especially 'Common Sub-expression Optimizations'. -  Some items should be unsigned in stead of int. Not a real problem.    Detected by checking the appropriateness and ranges of types. -  In some places an int is cast to unsigned, then tested for a 'large'    value including 'negative' values. This may be non-portable. -  Not checked for potential alignment problems. I don't think there are.___-------------------------------------------------------------------- */#include <stdlib.h>#include <string.h>           /* memcpy() */#include <assert.h>           /* debugging */#include "stack.h"#include "stk_defs.h"         /* MALLOC, CALLOC, FREE (re-)definitions  */                              /* and other debugging re-def's with a    */                              /* special debugging version.             */#define MEMORY          -1    /* Preparations/replacements for GP Error */#define Error(x)        (x)   /* manager. Error may terminate program.  */#define STACK_GROWTH    16struct StackHead{    char * base ;        /* base address for the stack (char * because  */                         /*     adding offset to void * doesn't work.)  */    unsigned offset ;    /* offset of data from base in bytes           */    int top ;            /* offset of data from base in items           */    int itemsize ;       /* itemsize * top should equal to offset       */    int max ;            /* max < top is an error                       */    int underflow ;      /* flag. Incremented when Pops exceed Pushes.  */};/*  --- local data and prototypes ------------------------------------- */static struct StackHead * StackArray ; /* initialised: StackSystemInit  */                                       /* modified by: StackCreate      */static int StackCount ;                /* same. Used by management only */static int StackInit( int Stack, int Itemsize );/* ---- Management operations ----------------------------------------- */int StackSystemInit( int StackCountAdditional ){    assert( (unsigned) StackCountAdditional <= 20 );                 /* negative is logic error (cast => neg. is large int) */                 /* higher than 20 is ridiculous for an initial setup   */    StackCountAdditional += STACK_COUNT_DEFAULT ;    /* Create and initialize stack 'descriptor' array. A zero value       for all bytes of a pointer is assumed to be a NULL pointer.    */    StackArray = CALLOC( StackCountAdditional, struct StackHead );    if( NULL == StackArray )    {        return Error( MEMORY );    }    /* Initialize each default stack.    */    if( StackInit( STACK_INT, sizeof( int )))    {        return Error( MEMORY );    }    if( StackInit( STACK_LONG, sizeof( long )))    {        return Error( MEMORY );    }    if( StackInit( STACK_PTRS, sizeof( char * )))    {        return Error( MEMORY );    }    if( StackInit( STACK_FAR_PTRS, sizeof( char FAR * )))    {        return Error( MEMORY );    }    StackCount = StackCountAdditional ;    return StackCount ;}static int StackInit( int Stack, int Itemsize ){    StackArray[ Stack ].itemsize  = Itemsize ;    StackArray[ Stack ].max       = STACK_GROWTH * 2 ;    StackArray[ Stack ].top       = 0 ;    StackArray[ Stack ].offset    = 0 ;    StackArray[ Stack ].underflow = 0 ;    StackArray[ Stack ].base = MALLOC( STACK_GROWTH *2 * Itemsize, char );    if( NULL == StackArray[ Stack ].base )    {        return MEMORY ;    }    return NO_PROBLEMS ;}int StackCreate( int ItemSize ){    int Stack ;    assert( (unsigned) ItemSize-2 <= 1022 );                     /* Not too small, too large or negative please !!! */    /* Look for empty slot    */    for( Stack = 0; Stack < StackCount; Stack++ )    {        if( NULL == StackArray[ Stack ].base )            break;    }    /*  What if NO EMPTY slot ???    */    if( Stack == StackCount )    {        struct StackHead * tmp ;         /* StackArray expansion needed */        tmp = realloc( StackArray,                       (StackCount + 1) * sizeof( struct StackHead ));        if( NULL == tmp )        {            return Error( MEMORY );        }        StackArray = tmp ;        StackCount ++ ;    }    if( StackInit( Stack, ItemSize ))    {        return Error( MEMORY );    }    return Stack ;}void StackDelete( int Stack ){    if( StackCheck( Stack ) < STACK_ERRORS )  /* OK if only warning */    {        FREE( StackArray[ Stack ].base );        StackArray[ Stack ].base = NULL ;    }    return ;}int StackAdapt( int Stack, int Free ){   assert( (unsigned) Stack < StackCount );    /* validate stack number */   assert( (unsigned) Free <= 4 * STACK_GROWTH );                       /* Negative and large numbers are ridiculous ... */                       /* assuming casted negative int = large unsigned */   while( StackArray[ Stack ].top + Free >= StackArray[ Stack ].max )   {        char * tmp ;    /* resize Stack in steps */        tmp = realloc( StackArray[ Stack ].base,                       StackArray[ Stack ].itemsize                        * (StackArray[ Stack ].max + STACK_GROWTH ));        if( NULL == tmp )        {            return MEMORY ;        }        StackArray[ Stack ].max += STACK_GROWTH ;        StackArray[ Stack ].base = tmp;   }   return NO_PROBLEMS ;}int StackCheck( int Stack )      /* Check for possible problems in more */{                                /* or less decreasing severity         */    if( (unsigned) Stack >= StackCount )    {        return STACK_INV_NUMBER ;    }    if( NULL == StackArray[ Stack ].base )    {        return STACK_NULL ;    }    if( StackArray[ Stack ].top > StackArray[ Stack ].max )    {        return STACK_CORRUPT2 ;    }    if( StackArray[ Stack ].top * StackArray[ Stack ].itemsize         != StackArray[ Stack ].offset )    {        return STACK_CORRUPT1 ;    }    if( 0 != StackArray[ Stack ].underflow )    {        StackArray[ Stack ].underflow = 0; /* reset underflow flag */        return STACK_UNDERFLOW ;    }    if( StackArray[ Stack ].top == StackArray[ Stack ].max )    {        return STACK_LIMIT_REACHED ;    }    if( 0 == StackArray[ Stack ].top )    {        return STACK_EMPTY ;    }    return NO_PROBLEMS ;}void StackUnpop( int Stack ) /* Reverse a pop. Data is still present!   */{                            /* very useful for implementing stacks     */                             /* with variable sized items ...           */    if( StackArray[ Stack ].top < StackArray[ Stack ].max )    {        StackArray[ Stack ].offset += StackArray[ Stack ].itemsize ;        StackArray[ Stack ].top ++ ;    }    return ;}/* ---- Generic push/pop operations ----------------------------------- */int Push( int Stack, void * Source ){    if( NO_PROBLEMS != StackAdapt( Stack, 1 ))    {        return MEMORY;    }    memcpy( StackArray[ Stack ].base + StackArray[ Stack ].offset,            Source,            StackArray[ Stack ].itemsize );    StackArray[ Stack ].offset += StackArray[ Stack ].itemsize ;    StackArray[ Stack ].top ++ ;    return NO_PROBLEMS ;}void Pop( int Stack, void * Destination ){    if( 0 != StackArray[ Stack ].top )  /* don't ACTUALLY underflow ... */    {        StackArray[ Stack ].offset -= StackArray[ Stack ].itemsize ;        StackArray[ Stack ].top -- ;    }    else        StackArray[ Stack ].underflow ++ ;    memcpy( Destination,            StackArray[ Stack ].base + StackArray[ Stack ].offset,            StackArray[ Stack ].itemsize );    return ;}/* ---- Push/pop operations to/from default stacks -------------------- */int PushInt( int Value ){    if( NO_PROBLEMS != StackAdapt( STACK_INT, 1 ))    {        return MEMORY;    }    * ((int *) ( StackArray[ STACK_INT ].base                  + StackArray[ STACK_INT ].offset )) = Value ;    StackArray[ STACK_INT ].offset += sizeof( int );    StackArray[ STACK_INT ].top ++ ;    return NO_PROBLEMS;}int PopInt( void ){    if( 0 != StackArray[ STACK_INT ].top )    {        StackArray[ STACK_INT ].offset -= sizeof( int );        StackArray[ STACK_INT ].top -- ;    }    else        StackArray[ STACK_INT ].underflow ++ ;    return * ((int *) ( StackArray[ STACK_INT ].base                         + StackArray[ STACK_INT ].offset ));}int PushLong( long Value ){    if( NO_PROBLEMS != StackAdapt( STACK_LONG, 1 ))    {        return MEMORY;    }    * ((long *) ( StackArray[ STACK_LONG ].base                   + StackArray[ STACK_LONG ].offset )) = Value ;    StackArray[ STACK_LONG ].offset += sizeof( long );    StackArray[ STACK_LONG ].top ++ ;    return NO_PROBLEMS;}long PopLong( void ){    if( 0 != StackArray[ STACK_LONG ].top )    {        StackArray[ STACK_LONG ].offset -= sizeof( long );        StackArray[ STACK_LONG ].top -- ;    }    else        StackArray[ STACK_LONG ].underflow ++ ;    return * ((long *) ( StackArray[ STACK_LONG ].base                          + StackArray[ STACK_LONG ].offset ));}int PushPtr( void * Value ){    if( NO_PROBLEMS != StackAdapt( STACK_PTRS, 1 ))    {        return MEMORY;    }    * ((char **) ( StackArray[ STACK_PTRS ].base                   + StackArray[ STACK_PTRS ].offset )) = Value ;    StackArray[ STACK_PTRS ].offset += sizeof( char * );    StackArray[ STACK_PTRS ].top ++ ;    return NO_PROBLEMS;}void * PopPtr( void ){    if( 0 != StackArray[ STACK_PTRS ].top )    {        StackArray[ STACK_PTRS ].offset -= sizeof( char * );        StackArray[ STACK_PTRS ].top -- ;    }    else        StackArray[ STACK_PTRS ].underflow ++ ;    return * ((char **) ( StackArray[ STACK_PTRS ].base                           + StackArray[ STACK_PTRS ].offset ));}int PushFptr( void FAR * Value ){    if( NO_PROBLEMS != StackAdapt( STACK_FAR_PTRS, 1 ))    {        return MEMORY;    }    * ((char FAR **) ( StackArray[ STACK_FAR_PTRS ].base                        + StackArray[ STACK_FAR_PTRS ].offset )) = Value ;    StackArray[ STACK_FAR_PTRS ].offset += sizeof( char FAR * );    StackArray[ STACK_FAR_PTRS ].top ++ ;    return NO_PROBLEMS;}void FAR * PopFptr( void ){    if( 0 != StackArray[ STACK_FAR_PTRS ].top )    {        StackArray[ STACK_FAR_PTRS ].offset -= sizeof( char FAR * );        StackArray[ STACK_FAR_PTRS ].top -- ;    }    else        StackArray[ STACK_FAR_PTRS ].underflow ++ ;    return * ((char FAR **) ( StackArray[ STACK_FAR_PTRS ].base                               + StackArray[ STACK_FAR_PTRS ].offset ));}/* === STACK.c end ==================================================== */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -