Generally, when writing a C program, you can use typedef to abstract the types of elements in the container. Two types cannot be used in the same program, this article tries to use two different types of containers in a program, such And vector . The core technology is to define the element type as void *, to manage what type it is, and use the void * type pointer to point to the real data. At the same time, the type size is an important information, for example, char is 1 byte and double is 4 bytes.
This article imitates the vector class in STL to write a vector structure in C language. To reflect encapsulation, the Vector type is defined as vector *. The program is as follows:
1. Vector Interface
/*************************************** * **************************** Created: 2014/02/07 22: 24 filename: vector. hauthor: Justme0 (http://blog.csdn.net/justme0) purpose: vector interface ************************************* * ******************************/# ifndef vector_h __# define vector_h _ typedef struct vector * Vector; typedef void ** vec_iterator; Vector vec_construct (int data_size); void vec_destruct (Vector V); int vec_size (Vector V); vec_iterator vec_begin (Vector V ); vec_iterator vec_end (Vector V); void vec_insert_n (Vector V, vec_iterator position, int n, void * pelem); void vec_push_back (Vector V, void * pelem ); # endif // vector_h __
2. Implementation of Vector
/*************************************** * **************************** Created: 2014/02/07 22: 25 filename: vector. cauthor: Justme0 (http://blog.csdn.net/justme0) purpose: implementation of Vector ************************************* * ******************************/# include "vector. h "# include
# Include
# Include
# Include
# Include
# Include
Typedef struct vector; typedef void * vec_value_type; struct vector {vec_iterator start; vec_iterator finish; vec_iterator end_of_storage; int elem_size ;};/*** data_size: size of the Data Type in the container */Vector vec_construct (int data_size) {Vector V = (vector *) malloc (sizeof (vector); if (NULL = V) {exit (OVERFLOW) ;}v-> start = NULL; V-> finish = NULL; V-> end_of_storage = NULL; V-> elem_size = data_size; return V ;} void vec_d Estruct (Vector V) {vec_iterator ite; for (ite = V-> start; ite! = V-> finish; ++ ite) {free (* ite);} free (V-> start); free (V);} vec_iterator vec_begin (Vector V) {return V-> start;} vec_iterator vec_end (Vector V) {return V-> finish;} int vec_size (Vector V) {return vec_end (V) -vec_begin (V);} void vec_insert_n (Vector V, vec_iterator position, int n, void * pelem) {int old_size = 0; int new_size = 0; int insert_index = 0; vec_iterator ite = NULL; // target pointer vec_iterator old_finish = NULL when moving elements; if (0 = n) {return;} insert_index = position-V-> start; old_size = vec_size (V); new_size = old_size + n; // check whether the remaining space is sufficient. if not, expand if (V-> end_of_storage-V-> finish <n) {const int new_capacity = old_size + _ max (old_size, n); vec_value_type * new_base = (vec_value_type *) realloc (V-> start, new_capacity * sizeof (vec_value_type )); if (NULL = new_base) {exit (OVERFLOW);} V-> start = new_base; V-> end_of_storage = V-> start + new_capacity ;} v-> finish = V-> start + new_size; old_finish = V-> start + old_size; // The Space indicated by old_finish may not be the original position = V-> start + insert_index; // move the element // source interval: [position, old_finish) // destination interval: [position + n, old_finish + n) for (ite = old_finish + n-1; ite >=position + n; -- ite) {assert (V-> start <= ite & ite <V-> finish ); assert (V-> start <= ite-n & ite-n <V-> finish); * ite = * (ite-n );} // insert n new elements to [position, position + n) for (; ite> = position; -- ite) {* ite = malloc (V-> elem_size ); if (NULL = * ite) {exit (OVERFLOW);} memcpy (* ite, pelem, V-> elem_size) ;}} void vec_push_back (Vector V, void * pelem) {vec_insert_n (V, vec_end (V), 1, pelem );}
3. Test Procedure
/*************************************** * **************************** Created: 2014/01/27 11: 46 filename: main. cppauthor: Justme0 (http://blog.csdn.net/justme0) purpose: Use void * in C to implement generics (test programs) **************************************** * ****************************/# include
# Include "vector. h"/*** output char type */void output_c (Vector V) {vec_iterator iter; for (iter = vec_begin (V); iter! = Vec_end (V); ++ iter) {printf ("% c \ n", * (char *) * iter ); // note that the true type of iter is void ***}/*** output double type */void output_d (Vector V) {vec_iterator iter; for (iter = vec_begin (V); iter! = Vec_end (V); ++ iter) {printf ("%. 2f \ n ", * (double *) * iter ); // note that the true type of iter is void ***}/*** test char type */void test1 () {char ch = 'A '; int cnt = 5; Vector my_vec = vec_construct (sizeof (char); while (cnt --) {vec_push_back (my_vec, & ch); ++ ch;} output_c (my_vec ); printf ("size is % d \ n", vec_size (my_vec); vec_destruct (my_vec);}/*** test double type */void test2 () {double d = 3.142; int cnt = 13; Vector my_vec = vec_construct (sizeof (double); while (cnt --) {vec_push_back (my_vec, & d ); ++ d ;}output_d (my_vec); printf ("size is % d \ n", vec_size (my_vec); vec_destruct (my_vec);} int main (int argc, char ** argv) {test1 (); printf ("\ n"); test2 (); return 0 ;}
4. Running result
ABCDEsize is 53.144.145.146.147.148.149.1410.1411.1412.1413.1414.1415.14size is 13 press any key to continue...
Because the element type is void *, The iterator type is void **. Therefore, you must convert the void * forced type to data_type * During output, and then unreference it.