如何使用C語言寫: Generic Stack

來源:互聯網
上載者:User

實現一個簡單的棧,並非難事,但是使用C語言編寫一個GenericStack還是有挑戰.本文使用自增長數組的方式實現棧.同樣遵循上篇("genericlist篇")所寫的C語言泛型設計的原則,再次不贅述.

 

模型

------------------------------------------------------------------------------------------------------------------------

核心代碼

------------------------------------------------------------------------------------------------------------------------

完整代碼詳見我的github(https://github.com/gnudennis/ds_c)(genric-stack.h
generic-stack.c generic-stack-test.c)

0. Generic Stack定義

typedef void *ElementAddr;typedef void (*PfCbFree)(ElementAddr);typedef struct StackRecord{        ElementAddr*array;        intelemsize;        intloglength;        intalloclength;        PfCbFreefreefn;} *Stack;

 

1. API的設計

/* Create a new stack */Stack stack_create(int elemsize, PfCbFree freefn);/* Dispose the stack */void stack_dispose(Stack stk);/* Make the given stack empty */void stack_make_empty(Stack stk);/* Return true if the stack is empty */int stack_is_empty(Stack stk);/* Insert a new element onto stack */void stack_push(Stack stk, ElementAddr elemaddr);/* Delete the top element off the stack */void stack_pop(Stack stk);/* Fetch the top element from the stack */void stack_top(Stack stk, ElementAddr elemaddr);/* Fetch & Delete the top element from the stack */void stack_top_and_pop(Stack stk, ElementAddr elemaddr);

將pop和top分開的目的是為了滿足不同的需求,同時添加了stack_top_and_pop作為補充.

 

2.實現

#define MIN_STACK_SIZE (4)/* Create a new stack */Stack stack_create(int elemsize, PfCbFree freefn){        Stack stk;                stk = malloc(sizeof(struct StackRecord));                if ( stk == NULL) {                fprintf(stderr, "Out of memory\n");                exit(1);        }                stk->array = malloc(elemsize * MIN_STACK_SIZE);        if (stk->array == NULL) {                fprintf(stderr, "Out of memory\n");                exit(1);        }        stk->elemsize = elemsize;        stk->loglength = 0;         stk->alloclength = MIN_STACK_SIZE;}/* Dispose the stack*/void stack_dispose(Stack stk){        stack_make_empty(stk);        free(stk->array);        free(stk);}/* Make the given stack empty*/void stack_make_empty(Stack stk){        if ( stk->freefn ) {                int i;                for ( i = 0; i < stk->loglength; ++i) {                        stk->freefn((char *)stk->array +                                     i * stk->elemsize);                }        }        stk->loglength = 0;}/* Return true if the stack is empty*/int stack_is_empty(Stack stk){        return stk->loglength == 0;}static void stack_grow(Stack stk){        stk->alloclength *= 2;        stk->array = realloc(stk->array,                              stk->alloclength * stk->elemsize);}/* Insert a new element onto stack */void stack_push(Stack stk, ElementAddr elemaddr){        ElementAddr target;        if ( stk->loglength == stk->alloclength )                stack_grow(stk);        target = (char *)stk->array + stk->loglength * stk->elemsize;        memcpy(target, elemaddr, stk->elemsize);        stk->loglength++;}/* Delete the top element off the stack */void stack_pop(Stack stk){        ElementAddr target;        if ( stack_is_empty(stk) ) {                fprintf(stderr, "Empty stack\n");                exit(1);        }        if ( stk->freefn ) {                target = (char *)stk->array +                          (stk->loglength-1) * stk->elemsize;        stk->freefn(target);        }        stk->loglength--;}/* Fetch the top element from the stack */void stack_top(Stack stk, ElementAddr elemaddr){        void *target = (char *)stk->array +                        (stk->loglength-1) * stk->elemsize;        memcpy(elemaddr, target, stk->elemsize);}/* Fetch & Delete the top element from the stack */void stack_top_and_pop(Stack stk, ElementAddr elemaddr){        ElementAddr target;        if ( stack_is_empty(stk) ) {                fprintf(stderr, "Empty stack\n");                exit(1);        }        target = (char *)stk->array +                  (stk->loglength-1) * stk->elemsize;        memcpy(elemaddr, target, stk->elemsize);        stk->loglength--;}

使用和測試

------------------------------------------------------------------------------------------------------------------------

測試代碼:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include "generic-stack.h"void strfreefn(ElementAddr elemaddr){        free(*(char **)elemaddr);}int main(int argc, char **argv){        Stack int_stk, str_stk;        int i;        char *names[] = {                 "C", "C++", "Jave", "C#", "Python",                 "PHP", "Basic", "Objective C", "Matlab", "Golang"         };        /* test integer stack */        printf("Test integer stack\n");        int_stk = stack_create(sizeof(int), NULL);        for ( i = 0; i < 10; ++i ) {                stack_push(int_stk, &i);        }        while ( !stack_is_empty(int_stk) ) {                int val;                stack_top_and_pop(int_stk, &val);                printf("%d\n", val);        }                stack_dispose(int_stk);        /* test string stack */        printf("Test string stack\n");        str_stk = stack_create(sizeof(char *), strfreefn);        for ( i = 0; i < 10; ++i ) {                char *copy = strdup(names[i]);                char *dest;                stack_push(str_stk, );        }                while ( !stack_is_empty(str_stk) ) {                char *dest;                stack_top_and_pop(str_stk, &dest);                printf("%s\n", dest);                free(dest);        }        stack_dispose(str_stk);        return 0;}

分析:

 

(1). int_stack (存放對象)

 

(2). str_stack(存放指標)

array存放的是一系列指標,這些指標指向的實際對象需要在堆中分配.那麼最初放入stack進行管理的對象來源不定,可能是堆,棧,甚至是常量區.為了便於管理,應該先在堆中分配這些對象(來來源物件的副本:上述的strdup操作)."一個元素一旦入棧,這個元素的控制權就交由棧進行管理,一旦出棧,這個元素的控制權就交由使用者管理".

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.