C语言使用 void 指针实现栈模板

数据结构基础课的教材使用C来实现数据结构,上学期看别的书用C++实现时还没什么感觉,一对比就发现C++的类和模板用起来比C方便多了。

在写四则运算计算器的时候,int写一遍,char还得写一遍感觉十分痛苦,百度了一下有没有别的解决办法,发现了下面这篇文章。

如何利用堆栈及逆波兰表达式进行数学四则运算:http://www.xuebuyuan.com/1602553.html

关键是在于理解 void 指针与一般指针的不同之处是它只保存数据的首地址,而不知道也不关心数据究竟有多少个字节。

因此利用 memcpy 可以无视数据类型进行赋值,这就让我们能够创建多种类型的Stack。

由于 memcpy 的参数是 void 指针,所以Push和Pop的都只接受地址作为参数,并且直接将改变应用于相应的内存单元,并不返回值。

此外,此处实现的Top指针也和一般的Stack定义不同,此处的Top指针总是指向下一个可用的内存单元。

仿照着写了一个Stack的实现如下:

 1 // This stack is implemented by void pointer, so it is GENERIC.
 2 //
 3 // How the void pointer allows assignments of different data types:
 4 //    first, a normal pointer is binded to a data type, so it knows the
 5 //    number of bytes of the data it points to. second, it has an address,
 6 //    which is the start-address of the data. so they can tell the compiler
 7 //    where to start and where to stop accessing the data.
 8 //
 9 //    but void pointer is binded to no data type,it only knows the starting-address.
10 //    so it can be forcely assigned to any pointers, thus allowing assignments of
11 //    all data types. so what we do is: when we create the stack, we MALLOC a block
12 //    of free space, and we take an integer of 'size_t', the typesize, which
13 //    specifies the length of the data. We use the function MEMCPY, which directly
14 //    access the addresses,to push the data in the stack and pop data out.
15 //
16 // The difference from the definiton:
17 //    the stack pointer here is different from the definition.
18 //    when the stack is empty, top == base.
19 //    when an element is pushed in, top points to the address after the last byte
20 //    of the element. so the top always points to the next available space.
21 
22 #include<stdio.h>
23 #include<stdlib.h>
24 
25 struct Record
26 {
27     void *top;
28     void *base;
29     int stacksize;
30     int typesize;
31 };
32 
33 typedef struct Record *Stack;
34 
35 Stack CreateStack(int stacksize, size_t typesize);
36 void Push(Stack S, void *data);
37 void Pop(Stack S, void *data);
38 int IsEmpty(Stack S);
39 void Clear(Stack S);
40 void Destroy(Stack S);
 1 #include"stack.h"
 2 #include<string.h>
 3 
 4 Stack CreateStack(int stacksize, size_t typesize)
 5 {
 6     Stack S = (Stack)malloc(sizeof(struct Record));
 7     S->base = malloc(stacksize*typesize);
 8     if(!S->base)
 9     {
10         printf("Out of space.\n");
11         exit(1);
12     }
13 
14     S->top = S->base;
15     S->stacksize = stacksize;
16     S->typesize = typesize;
17 
18     return S;
19 }
20 
21 void Push( Stack S, void *data)
22 {
23     if( (int)(S->top - S->base) + S->typesize > S->stacksize )
24     {
25         printf("Out of space to Push.\n");
26         exit(1);
27     }
28 
29     memcpy(S->top, data, S->typesize);
30     S->top = (void*)( (int)S->top + S->typesize );
31 }
32 
33     // GNU defines the arithmetic of void* equals to char(which is defined as byte).
34     // ANSI says we cannot do arithmetic on void* because we don't know the type.
35     // so when we update the top pointer, first regard it as an int, and convert it
36     // back when we are finished.
37 
38 void Pop( Stack S, void *data)
39 {
40     if( S->top == S->base )
41     {
42         printf("Error:Popping an empty stack.\n");
43         exit(1);
44     }
45 
46     S->top = (void*)( (int)S->top - S->typesize);
47     memcpy(data, S->top, S->typesize);
48 }
49 
50 void Clear(Stack S)
51 {
52     S->top = S->base;
53 }
54 
55 int IsEmpty(Stack S)
56 {
57     return S->top == S->base;
58 }
59 
60 void Destroy(Stack S)
61 {
62     free(S->base);
63 }

 

posted @ 2014-09-28 16:47  jeffo  阅读(811)  评论(0)    收藏  举报