How not to repeat yourself in this situation? C functions that are the same but have different arguments

Now I know what you think - the thing that I described in the title sounds just like overload. I know that this is not something in C, and I am not going to do it anyway. I have these 2 functions - ABSOLUTELY the same in their body, but the arguments are two different structures. This is mainly the binary structure of the search tree and the red black tree structure. As you know, structures have only one difference: the red black tree structure contains one more field and a color one. In addition, the search for functions, min, max, predecessor, successor .. they will have EXACTLY the same body, but, alas, they take 2 different types of structures. And of course, the insert and delete methods will be different.

So, I was thinking, how can I avoid breaking rule number one in programming and not repeat myself? I thought of a lot of solutions, but no one works when I try to find a way to implement it. I was thinking that I just use the same function for both, but I cannot do this because the structures are different. I thought about using macros, but to be honest, I have no idea how to do this, and I'm not even sure that they can avoid the problem that I have two different structures. I thought about creating one generic structure and contained it in the rb structure and the color variable, but this directly changes the code with several characters everywhere, since I need to go one level deeper into the structure to get the values, and I no longer have duplicate code .

Just an example of a problem:

bst_search(bstTree t, char *k)
{
    // Searching in tree
}

rb_search(rbTree t, char *k)
{
    // SAME code for searching in tree
}

java, , , , , C .

: , . , , , - ( ofc).

, , .

+4
3

rbTree bstTree , :

typedef struct
{
   bstTree common ;
   int color ;
} rbTree

rbTree bstTree, rb_search() , :

#define rb_search(t, k) bst_search( (bstTree*)(t). k )

, , rbTree, common. , , ; rbTree bstTree, , , , , - . , , include #include .

+2

C ( ++, ).

№1. :

#define MAKE_SEARCH_FUNCTION(FN_NAME, VAR_TYPE) \
FN_NAME(VAR_TYPE t, char *k) \
{ \
    /* Searching in tree */ \
}

struct bstTree {
};
MAKE_SEARCH_FUNCTION(bst_search, struct bstTree*)

struct rbTree {
};
MAKE_SEARCH_FUNCTION(rb_search, struct rbTree*)

№2. include. , , (, bst_search()/bst_add()/bst_remove()).

//header.h

FN_NAME(VAR_TYPE t, char *k) 
{
    // Searching in tree
}

//source.c

struct bstTree {
};
#define VAR_TYPE struct bstTree*
#define FN_NAME bst_search
#include "header.h"
#undef VAR_TYPE
#undef FN_NAME

struct rbTree {
};
#define VAR_TYPE struct rbTree*
#define FN_NAME rb_search
#include "header.h"
#undef VAR_TYPE
#undef FN_NAME
0

, , , , - .

. :

struct genericTree {
  // common members for both trees 
 ... 
  // members for rb trees 
 ... 
  // members for bst
 ... 
} 

:

search(genericTree* t, char* k) 

, typedefs:

typedef genericTree bstTree;
typedef genericTree rbTree;

, , bstTree rbTree, , .

The disadvantage of this approach is that you take more memory for one tree, because you are holding members of another. Perhaps you can facilitate it with some unions.

0
source

All Articles