I don't use the C language since years and now I need it again.
I'm trying to build a Red-Black Tree but I'm stuck at the beginning because I'm missing something about "structs".
Take a look to my "structs" declarations please, they are easy.
This is a header file included in Red_black_tree.c
#define BLACK 0 //defalut color
#define RED 1 //
struct Node { //create a black node by default, to have a red one look at "create_red_node"
struct Node *left = NULL;
struct Node *right= NULL;
int key = 0;
int value = 0;
char color = BLACK;
};
struct Root_t {
struct Node* Root;
};
struct Node* create_node () {
struct Node* black = (Node*) malloc (sizeof(Node));
return black;
}
struct Node* create_red_node () {
struct Node* red = create_node ();
red->color=RED;
return red;
}
Root_t* create_tree () {
struct Root_t* fake=(Root_t*) malloc (sizeof(Root_t));
struct fake->Root->left=create_red_node ();
struct fake->Root->right=create_red_node ();
return fake;
}
I compiled with "gcc Red_black_tree.c -o RBTree".
GCC says something like : "expected ';' at end of declaration list" 7 times, or "must use 'struct' tag to refer to type... ", "expected identifier...".
What do you think, is it good to create RBTree?
In C, you can not assign while you define the members of a struct
Instead of
struct T {
int a = 1;
int b = 2;
};
you need something like
struct T {
int a;
int b;
};
...
struct T t = {.a = 1, .b = 2};
In addition, all your members are set to 0 (NULL is an alias of (void *)0), when you want to allocate memory and initialize all to zero at the same time you can use calloc
struct Node* black = calloc(1, sizeof(*black)); // Dont cast malloc and friends
And here:
struct fake->Root->left=create_red_node();
, you don't want the struct keyword, instead:
fake->Root->left=create_red_node();
Another suggestion: do not hardcode the data of the red-black-tree in the structure, (int key, value;) even if it works you end up with a non reusable container, instead, use a generic pointer to void (void *data;) and a callback to your comparison functions in the implementation.
struct Node *insert(struct Node *root, int (*comparer)(const void *, const void *)) ...
Related
In the tree.h header, I declared "struct privates" in order to hide the global variables. (relevant snippet)
struct privates;
/*
* a tree
*/
typedef struct tree_node
{
struct tree *left;
struct tree *right;
struct tree_node *left;
struct tree_node *right;
float * info;
float distance_to_neighbor;
} tree_node;
typedef struct tree
{
/*in order to keep track of the kd-tree root*/
tree_node * _root;
/*pointer to internal variables struct*/
struct privates* _privates;
} tree;
struct privates* init_heap_tree();
etc....
In the implementation file kdtree.c , I defined the "struct privates": (relevant snippet)
tree* my_tree=NULL;
typedef struct privates
{
/*variables*/
int current_number_of_tree_nodes;
/*previous tree rebuild's node count*/
int previous_tree_size;
} privates;
privates* init_heap_tree()
{
return (privates*) calloc(1, sizeof (privates));
}
tree* tree_get_tree()
{
my_tree = get_pre_allocated_tree();
return my_tree;
}
etc...
Now in the memory management code, see relevant snippet of init_heap().
I’m attempting to set initialize values for struct members "tree_space->_privates->current_number_of_tree_nodes = 0;"
void
init_heap (int max_dimensions)
{
tree_space = (tree *) calloc (tree_HEAP_SIZE, sizeof (tree));
tree_space = get_pre_allocated_tree();
tree_space->_privates = init_heap_tree();
//THIS IS WERE COMPILE TIME ERROR OCCURS
tree_space->_privates->current_number_of_tree_nodes = 0;
tree_space->_privates->previous_tree_size =0;
//allocate memory based on tree_HEAP_SIZE
tree_space = (tree_node*) calloc (tree_HEAP_SIZE, sizeof (tree_node));
tree_set_k_dimensions (max_dimensions);
etc...
}
"error: dereferencing pointer to incomplete type "struct privates"
I don't want any other design pattern for information hiding perse, How can I resolve this error with the struct member access?
Thanks a million.
Only functions in kdtree.c can access the members of private, so you need to do the initialization there.
privates* init_heap_tree()
{
privates *rval = calloc(1, sizeof (privates));
rval->current_number_of_tree_nodes = 0;
rval->previous_tree_size = 0;
return rval;
}
I'm new to C and trying to compile this simple code, but it's not working and I'm not sure why. Can anyone help me?
int main(int argc, const char * argv[])
{
struct Node{
int value;
struct Node *next;
};
struct Node* x;
struct Node* y;
struct Node* z;
x = malloc(sizeof(Node));
y = malloc(sizeof(Node));
z = malloc(sizeof(Node));
return 0;
}
The compiler is complaining about the use of an undeclared identifier ‘Node’:
x = malloc(sizeof(Node));
y = malloc(sizeof(Node));
z = malloc(sizeof(Node));
Welcome to SO and the wonderful world of C!
A few pointers for you:
Syntax-ically there's no problem with defining a struct inside a function, but typically it's defined outside so that it can be used in other functions. For example:
main(){
struct nodedef{vars};
add_to_node(node var);
}
add_to_node(node var)
{
// How can I add a to a node when I don't know what that is?
}
The main problem with your code is that you aren't correctly referencing your node later on, if I declaire:
struct me {
int i;
};
Then anytime I reference this type of struct, I have to explicitly say struct again:
struct me myself;
myself = malloc(sizeof(struct me));
myself.i = 5;
The way to avoid this reuse of the struct keyword is to use the typedef:
typedef struct me {
int i;
}m;
m myself;
myself = malloc(sizeof(m));
myself.i = 5;
Last point is anytime you allocate some memory via malloc() make sure you call free() to release that memory:
free(myself);
Or else you'll have a memory leak.
Try sizeof(struct Node) instead.
struct Node should be used to refer to the structure. If you want the code above works, an alternative is typedef-ing the struct Node structure as
typedef struct Node {
int value;
struct Node *next;
} Node;
I would like to get some help with the following question.
I have a struct Node and I want to change it's insides using some method.
and I want to print the content of the changed struct inside my main method.
how do I get the struct changed and see the changed value in my main without returning the node as a return value.
I guess it might be solved with passing the struct Node as a pointer and then editing it.
what is the right way to do so?
for example:
typedef struct Node{
struct Node * right;
struct Node * left;
void * data;
}Node;
void insert(void * element, Node* root){
if(root==NULL){
root=(Node*)malloc(sizeof(Node));
root->data=element;
}
}
int main(){
Node a;
int b=8;
insert(&b,&a);
printf("%d",*(int*)a.data);
return 0;
}
printf doesn't print 8 it prints 1 (i guess some garbage)
It sounds like you are trying to do the following
Create a struct in one method, say main
Pass it to a second method, say example
Have example modify the struct and have the results visible in main
If so then the way to do this in C is by passing the struct as a pointer to example.
struct Node {
int data;
struct Node* pNext;
};
void example(struct Node* pNode) {
pNode->data = 42;
pNode->pNext = NULL;
}
int main() {
struct Node n;
example(&n);
printf("%d\n", n.data);
}
EDIT
Responding to the updated question.
To see the result of a modification of a Node you must pass a Node*. And accordingly to see the result of a Node* modification you need to pass a Node**. Essentially you need to pass one more level of indirection than the value you want to mutate / return.
void insert(void* element, Node** ppRoot){
if (NULL == *ppRoot) {
Node* pTemp = malloc(sizeof(Node));
pTemp->data = element;
*ppRoot = pTemp;
}
}
It's amazing how even the littlest program can cause so much trouble in C.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int value;
struct node *leftChild;
struct node *rightChild;
} node;
typedef struct tree {
int numNodes;
struct node** nodes;
} tree;
tree *initTree() {
tree* tree = (tree*) malloc(sizeof(tree));
node *node = (node*) malloc(sizeof(node));
tree->nodes[0] = node;
return tree;
}
int main() {
return 0;
}
The compiler says:
main.c: In function 'initTree':
main.c:17: error: expected expression before ')' token
main.c:18: error: expected expression before ')' token
Can you please help?
You're using two variables named tree and node, but you also have structs typedefed as tree and node.
Change your variable names:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int value;
struct node *leftChild;
struct node *rightChild;
} node;
typedef struct tree {
int numNodes;
struct node** nodes;
} tree;
tree *initTree() {
/* in C code (not C++), don't have to cast malloc's return pointer, it's implicitly converted from void* */
tree* atree = malloc(sizeof(tree)); /* different names for variables */
node* anode = malloc(sizeof(node));
atree->nodes[0] = anode;
return atree;
}
int main() {
return 0;
}
tree and node is your case are type names and should not be used as variable names later on.
tree *initTree() {
tree *myTree = (tree*) malloc(sizeof(tree));
node *myNode = (node*) malloc(sizeof(node));
myTree->nodes[0] = myNode;
return myTree;
}
Change (tree*) and (node*) to (struct tree*) and (struct node*). You can't just say tree because that's also a variable.
Change the body of initTree as follows:
tree* myTree = (tree *)malloc(sizeof(tree));
node *myNode = (node *)malloc(sizeof(node));
myTree->nodes[0] = myNode;
return myTree;
Don't use typedef'ed names as variable names, and there is not need to cast malloc(); in C.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int value;
struct node *leftChild;
struct node *rightChild;
} node;
typedef struct tree {
int numNodes;
struct node** nodes;
} tree;
tree *initTree() {
tree->nodes[0] = malloc(sizeof(node));
return malloc(sizeof(tree));
}
int main() {
return 0;
}
I second that Mehrdad's explanation is to the point.
It's not uncommon that in C code you define a variable with the same name as the struct name for instance "node node;". Maybe it is not a good style; it is common in, e.g. linux kernel, code.
The real problem in the original code is that the compiler doesn't know how to interpret "tree" in "(tree*) malloc". According to the compiling error, it is obviously interpreted as a variable.
Apart from the original question, this code, even in it's correct forms will not work, simply due to the fact that tree::nodes (sorry for the C++ notation) as a pointer to a pointer will not point to anything usefull right after a tree as been malloced. So tree->nodes[0] which in the case of ordinary pointers is essentially the same like *(tree->nodes), can't be dereferenced. This is a very strange head for a tree anyway, but you should at least allocate a single node* to initialize that pointer to pointer:
tree *initTree() {
/* in C code (not C++), don't have to cast malloc's return pointer, it's implicitly converted from void* */
tree* atree = malloc(sizeof(struct tree)); /* different names for variables */
/* ... */
/* allocate space for numNodes node*, yet numNodes needs to be set to something beforehand */
atree->nodes = malloc(sizeof(struct node*) * atree->numNodes);
node* anode = malloc(sizeof(struct node));
atree->nodes[0] = anode;
return atree;
}
Interestingly, it does compile cleanly if you simply write the allocations as:
tree *tree = malloc( sizeof *tree );
It is often considered better style to use "sizeof variable"
rather than "sizeof( type )", and in this case the stylistic
convention resolves the syntax error. Personally, I think
this example is a good case demonstrating why typecasts are
generally a bad idea, as the code is much less obfuscated if
written:
struct tree *tree = malloc( sizeof *tree );
Hey,
I'm a beginner in C and tried to implement my own linked list implementation, that basically looks like this:
struct Element
{
void *value;
struct Element *next;
};
typedef struct
{
struct Element *first;
struct Element *last;
unsigned int size;
} LinkedList;
void LinkedList_init(LinkedList *this)
{
this->size = 0;
this->first = NULL;
this->last = NULL;
}
void LinkedList_add(LinkedList *this, void *value)
{
struct Element *node = malloc(sizeof(struct Element));
node->value = value;
node->next = NULL;
if (this->size == 0)
this->first = this->last = node;
else
{
this->last->next = node;
this->last = node;
}
this->size++;
}
So in short, I want a linked list that can hold arbitrary types - I heard, this is possible in C by using void pointers.
The problem now arises, when I want to use that implementation, for example with a structure as value:
typedef struct
{
int baz;
} Foo;
int main(void)
{
LinkedList list;
Foo bar;
bar.baz = 10;
LinkedList_init(&list);
LinkedList_add(&list, (void *) &bar);
/* try to get the element, that was just added ... */
Foo *firstElement = (Foo *)list.first;
/* ... and print its baz value */
printf("%d\n", firstElement->baz);
return 0;
}
The last printf call just prints values like -1077927056, which look like a memory address. So it's probably a problem with pointers. After searching the web the last few days for a similar issue on the web (I had no luck with that), I tried to throw my own logic away and tested various random *& combinations. Turns out, that was a dead end, too. :(
It's probably something simple for a more experienced C programmer, but I just can't find the answer. Please help :D
list.fist is a struct Element.
Try:
Foo *firstElement = (Foo *)(list.first->value);