C-language implementation supports generic stack __c language

Source: Internet
Author: User
Tags assert reserved

In this blog post we are ready to use C to implement a support generics, as we all know, C + +

There is a template mechanism to support generics (the so-called generic stack is actually a stack that can hold any type including user-defined types), so how do we support generics for C?

One: First we implement a specific type of stack (for example, to store an integral type of stack), to see the implementation stack general

What is required:

We are divided into three documents to achieve (STACK.H;STACK.C; MAIN.C):

Stack.h//Declaration files, which include definitions of stack and corresponding operations (functions).

//stack.h:declaration file
// 
//version:1.1
//Date:12 September 2014
//Author:yu Maosheng
//email:yums467@nenu.edu.cn/
Co Pyright (c) 20014. All Rights Reserved.
//   History:/
*
12.12.2014 11:12       Yu maosheng
	Added int type Stack declaration;
///
define an integral type stack
typedef struct 
{
	//point to stack space element
	int *element;
	stack top pointer
	int loglength;
	The length of the stack when initializing
	int alloclength; 
} stack;
Declares the function
void stacknew (Stack *s) of the initialization stack
; Declares the function of the destroy stack
void Stackdispose (Stack *s);
Declares a function
void Stackpush (stack *s, int value) that pushes an element into the stack;
Declares the function
int stackpop (stack *s) that exits an element from the stack;

Through this header file we can see implementation of a stack, we need a stack space, a indicating stack top

Element, we also add an element that indicates the size of the stack space for ease of implementation.

At the same time we have operations for the stack implementation: Initialize the stack, push an element, exit an element,

Destroy the stack.

The following STACK.C file is the implementation of the function declared inside the Stack.h.

Stack.c:implementation file////Version : 1.1//Date:12 September 2014//Author:yu Maosheng//email:yums467@nenu.edu.cn//Copyright (c) 20014.
All Rights Reserved.
History:/* 12.12.2014 11:12 Yu maosheng Added int Stack function implementation; * * #include <stdlib.h> #include <assert.h> #include the implementation of "Stack.h"//stacknew void stacknew (Stack *s) {//Initialize top of stack
	The position of s->loglength = 0;
	Set the initial size of the stack (should be understood as the number of stored elements) S->alloclength = 4;
	Allocate stack space s->element = malloc (s->alloclength * sizeof (int));
	Check that the address is assigned a successful assert (S->element!= NULL);
Return
	//stackdispose implementation void Stackdispose (stack *s) {//Free stack space (s->element);
Return 
		//stackpush implementation void Stackpush (stack *s, int value) {//check stack space is full, if full expand space if (s->loglength = = s->alloclength) {
		S->alloclength *= 2;
		S->element = ReAlloc (s->element, s->alloclength * sizeof (int)); ASSERT (S->elemENT!= NULL);
	///Place the element on top of the stack//printf ("%d \ n", s->loglength);

	s->element[s->loglength++] = value;
Return
	Implementation of the//stackpop function int stackpop (stack *s) {//eject the stack top element assert (S->loglength > 0);
Return s->element[--s->loglength];
 }
The above code enables us to implement the operation on the specific stack. Now let's go over this stack

Test work to see if we have implemented this stack correctly.

Main.c

//Main.c:test file
//// 
version:1.1
//Date:12 September 2014
//Author:yu Maosheng
//email:yums467@nenu.edu.cn/
/Copyright (c) 20014. All Rights Reserved.
//   History:/
*
12.12.2014 18:00       Yu maosheng
Added int Stack Test in Main;
* *
#include "Stack.h"

int main (int argc, char const *argv[])
{
	Stack s;
	Stacknew (&s);

	for (int i = 0; i < 4; ++i)
	{
		Stackpush (&s, i);
	}
	printf ("%d\n", Stackpop (&s));
	Destroy Stack
	stackdispose (&s);
	return 0;
}
After execution, the program output 3 in the console, which shows that our implementation is correct.


Second, according to the above, we have implemented a stack of data can be stored, and implemented the

Stack operations (stack initialization, stack, stack, destroy Stack), but for a stack, we can not

Just to store the integer data, what if I want to store the double type of data? A

The way is that we implement a double type stack, and if I want to store a custom type of

What about the data. It seems that the above way is not workable, here we are going to implement a support for generics

Stack, the trick to implementing a generic stack is to use void pointers.

First we want to modify the definition of the structure stack, which will point to the pointer element elements of the stack space by int*

Instead, add a variable int elemsize that indicates the size of the user's data structure. viod*

Then we have to modify the declaration of functions on some of the stack operations:

The function that declares the initialization stack

void Stacknew (Stack *s, int elemsize);
function argument to add an int elemsize, which will be used to make space for the stack when deciding each dollar

The size of the element.

Declares a function that pushes an element into the stack
//void stackpush (stack *s, int value);
void Stackpush (Stack *s, void *elemaddr);
Add parameter void *elemaddr to indicate the address of the stack element to be entered

Declares a function that exits an element from the stack
//int stackpop (Stack *s);
void Stackpop (Stack *s,void *elemaddr);
Add parameter void *elemaddr to indicate the address used to store the stack element

This is the modification stack.h made.

Up to now the Stack.h file code is as follows:

/////////////////////////////////////////////////////////////////////////Stack.h:declaration File////version:1.1//DATE:12 September 2014//Author:yu Maosheng//email:yums467@nenu.edu.cn//Copyright (c)
20014. All Rights Reserved.

History:/* 12.12.2014 11:12 Yu maosheng Added int type Stack declaration;
12.12.2014 18:37 Yu Maosheng modifies the definition of the stack structure; 12.13 2014 13:42 Yu Maosheng modified the definition of Stacknew,stackpush,stackpop three functions///define an integral stack typedef struct {//point to stack space elements/
	int *element;
	Support generics, redefine stack space element void *element;
	Add a variable int elemsize that indicates the size of the user's data structure;
	stack top pointer int loglength; 
The length of the stack at initialization int alloclength;
}stack;
Declares the function of the initialization stack//void stacknew (stack *s);
void Stacknew (Stack *s, int elemsize);
Declares the function of the Destroy stack void Stackdispose (stack *s);
Declares a function that pushes an element into the stack//void stackpush (stack *s, int value);
void Stackpush (Stack *s, void *elemaddr);
Declares a function that exits an element from the stack//int stackpop (stack *s);

void Stackpop (Stack *s,void *elemaddr); 
To continue, we modify the Stack.c file to modify the implementation of the above function.

1.stackNew function to modify the allocated space code, the size of the space is no longer

S->alloclength * sizeof (int), but s->alloclength * elemsize.

void Stacknew (Stack *s, int elemsize)
{
	//Initialize stack top position
	s->loglength = 0;
	Set the initial size of the stack
	s->alloclength = 4;
	Assigning value s->elemsize = elemsize to stack member Elemsize
	;
	Allocate stack space
	s->element = malloc (S->alloclength * elemsize);
	Check that the address is assigned a successful
	assert (S->element!= NULL);
	return;
}

2.stackPush function to modify the space growth code, elements into the stack code.

For the elegance of the code, we encapsulate the space growth code into a function Stackgrow (),

When we get the top of the stack, we can no longer simply use the top element loglength to indicate,

We need to find the corresponding stack top position from the specific memory address.

void *target = (char *) (s->element) + s->loglength * s->elemsize;
The target pointer indicates the memory address at the top of the stack, and we copy the address of the stack element to the top address of our stack:

memcpy (target, elemaddr, s->elemsize);

The specific implementation code is as follows:

void Stackpush (Stack *s, void *elemaddr)
{
	//check stack space is full, if full expand space if
	(s->loglength = = s->alloclength)
	{
		//s->alloclength *= 2;
		S->element = ReAlloc (s->element, s->alloclength * sizeof (int));
		Call the growth stack space function
		stackgrow (s);
		ASSERT (S->element!= NULL);
	}
	Place the element on top of the stack
	//printf ("%d \ n", s->loglength);
	s->element[s->loglength++] = value;
	Get stack top address
	void *target = (char *) (s->element) + s->loglength * s->elemsize;
	memcpy (target, elemaddr, s->elemsize);
	s->loglength++;
	printf ("%d%d%s\n", S->loglength, S->elemsize, (char *) (s->element) + (s->loglength-1) * s->elemsize); return
	;
}
The 3.stackPop function is similar to where the Stackpush is modified, primarily to look for changes in the address of the top element of the stack,

We use the source pointer to indicate the top address of the stack.

void Stackpop (Stack *s, void *elemaddr)
{
	//eject the stack top element
	assert (S->loglength > 0);
	s->loglength--;
	void *source = (char *) (s->element) + (s->loglength-1) * s->elemsize;
	memcpy (elemaddr, source, s->elemsize);
	s->loglength--;
	printf ("pop:%d", s->loglength);
	Return s->element[--s->loglength];
}
So the code for the STACK.C population is as follows:

Stack.c:implementation file////Version : 1.1//Date:12 September 2014//Author:yu Maosheng//email:yums467@nenu.edu.cn//Copyright (c) 20014.
All Rights Reserved.
History:/* 12.12.2014 11:12 Yu maosheng Added int Stack function implementation; 12.13.2014 13:44 Yu Maosheng modified the Stacknew,stackpush,stackpop implementation to add the Stackgrow function */#include <stdlib.h> #incl Ude <stdio.h> #include <assert.h> #include <string.h> #include "Stack.h"//Growth stack space function static void stackgr
	ow (Stack *s) {s->alloclength *= 2;

	S->element = ReAlloc (s->element, s->alloclength * s->elemsize);
Return
	//stacknew implementation void Stacknew (stack *s, int elemsize) {//Initialize stack top position s->loglength = 0;
	Set the initial size of the stack s->alloclength = 4;
	Assigning value s->elemsize = elemsize to stack member elemsize;
	Allocate stack space s->element = malloc (S->alloclength * elemsize);
	Check that the address is assigned a successful assert (S->element!= NULL);Return
	//stackdispose implementation void Stackdispose (stack *s) {//Free stack space (s->element);
Return //stackpush implementation void Stackpush (stack *s, void *elemaddr) {//check stack space is full, if full expand space if (s->loglength = = S->alloclengt
		h) {//s->alloclength *= 2;
		S->element = ReAlloc (s->element, s->alloclength * sizeof (int));
		Call the growth stack space function stackgrow (s);
	ASSERT (S->element!= NULL);
	///Place the element on top of the stack//printf ("%d \ n", s->loglength);
	s->element[s->loglength++] = value;
	Get stack top address void *target = (char *) (s->element) + s->loglength * s->elemsize;
	memcpy (target, elemaddr, s->elemsize);
	s->loglength++; 
	printf ("%d%d%s\n", S->loglength, S->elemsize, (char *) (s->element) + (s->loglength-1) * s->elemsize);
Return
	The implementation of the//stackpop function void Stackpop (stack *s, void *elemaddr) {//eject the stack top element assert (S->loglength > 0);
	s->loglength--;
	void *source = (char *) (s->element) + (s->loglength-1) * s->elemsize; memcpy (ELEMADDR, source, s->elemsize);
	s->loglength--;
	printf ("pop:%d", s->loglength);
Return s->element[--s->loglength];
 }
Next we use the Main.c file to test

Main.c:test file////version:1.1//Date: September 2014//Author:yu Maosheng//email:yums467@nenu.edu.cn//Copyright (c) 20014.
All Rights Reserved.
History:/* 12.12.2014 18:00 Yu maosheng Added int Stack Test in Main; 12.13.2014 14:22 yu Maosheng Add test Case (string array) 2014 12.19 13:00 yu Maosheng test program to support generic stacks to find out where a segment error occurred Stackpush (&
Strstack, copy); Here is the error: The address of the copy variable should be taken as the parameter of the push function Stackpush (&strstack, &copy); it's like this. Because writing to the stack should be the address of the string rather than the string itself. #include <string.h> #include <stdio.h> #include <stdlib.h> #include "Stack.h" #pragma warning (disable
	: 4996)//This is because strdup error int main (int argc, char const *argv[]) {const char *friends[] = {"Alex", "Bob", "Caser"};
	Stack strstack;
	
	Stacknew (&strstack, sizeof (char *));
		for (int i = 0; i < 3; ++i) {//stackpush (&s, i); StrDup function: Copy the string to the new location//strdup internally called malloc () to allocate memory for the variable,//No need to use the returned string, free () release//corresponding memory space is required, or it can cause a memory leak.
		Char *copy = StrDup (Friends[i]);
		Stackpush (&strstack, &copy);
	Free (copy);
		for (int j = 0; J < 3; J + +) {char *name;
		name = malloc (sizeof (char *));
		Stackpop (&strstack, &name);
		printf ("%s\n", name);
	Free (name);
	}//printf ("%d\n", Stackpop (&s));
	Destroy Stack Stackdispose (&strstack);

	printf ("over\n");
return 0; }
We pushed three strings to the stack and then rolled the three strings back up the stack and output it to the console:



I would like to emphasize that in the past, when we implement the stack, the stack space element is stored in the stack element.

itself, and for the generic stack, we are holding pointers to the elements in the generic stack space.

Take the three strings above for example, we have a pointer to "Carse" in the stack instead of "Carse."

Itself.

It seems that the problem has been solved. Is it. If our stack element itself is a pointer or a handle

What to do (they themselves also open up storage space, we need to release these spaces). Here we are going to revise

The definition of the stack structure, in which a pointer member is added to the function, which is used specifically to

User-defined to implement free custom data type space.

void (*freefn) (void *element);

We assign values to function pointers in this structure in the Stacknew function.

Modify Stacknew as follows:

void Stacknew (Stack *s, int elemsize, void (*freefn) (void *element))
{
	//Initialize stack top position
	s->loglength = 0;
	Set the initial size of the stack
	s->alloclength = 4;
	Assigning value s->elemsize = elemsize to stack member Elemsize
	;
	assigning value
	S->freefn = freefn to function pointers;
	Allocate stack space
	s->element = malloc (S->alloclength * elemsize);
	Check that the address is assigned a successful
	assert (S->element!= NULL);
	return;
}
Add a parameter to the Stacknew function to initialize the pointer function member of the stack.


To modify the Stackdispose function:

void Stackdispose (Stack *s)
{
	if (s->freefn!= NULL)
	{for
		(int i = 0; i < s->loglength; i++)
		{
			S->freefn ((char *) s->element + i * s->elemsize);
		}
	Release stack space free
	(s->element);
	return;
}
In practical application, we define the application method of data structure space according to our own definition.
void (*freefn) (void *element);
The concrete implementation function, and as a parameter in the stack initialization when the value assigned.

So we have implemented a stack that supports generics in a complete form.



















Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.