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 }

浙公网安备 33010602011771号