Initializing a struct within a union within a struct in C - c

struct huffnode{
int freq;
union{
struct children
{
struct huffnode * l;
struct huffnode * r;
}
char c;
}un;
};
I'm trying to create a program that implements a huffman tree but in order to do that I need to create nodes with a left and right node pointer in them. The problem is that I don't know how to initialize the struct children. Anyone have any ideas?

Related

Making a generic linked list implementation that can be used with different sized structs

Hi I am currently working on a project where I am creating a very simple filesystem and I am working on some inode and general file cache implementations and I was wondering considering structs like this:
typedef struct disk_inode {
short type; /* file type */
short nlinks; /* number of directory entries referring to this file
int size; /* file size in bytes */
short inode_indir_idx;
/* pointers to the first NDIRECT blocks */
blknum_t direct[INODE_NDIRECT];
blknum_t indirect; /* The rest of the blocks */
}disk_inode_t;
struct cache{
short blocknr;
char block[512];
};
is there a way to create a generic list which can be used by both of these structures? This is in C and I cannot use any standard c libraries.
You can create a generic linked list which would take a void * as its element. Such implementation would require you to allocate your element in most cases though.
Here is a symple example:
typedef struct list_s
{
void *elm;
struct list_s *next;
struct list_s *prev;
} list_t;
typedef struct
{
int elem1;
int elem2;
int elem3;
} my_struct_t;
int main(void)
{
my_struct_t *elem = malloc(sizeof(my_struct_t));
list_t *list = malloc(sizeof(list_t));
list->prev = NULL;
list->next = NULL;
list->elm = elem;
return 0;
}

BST Links and cases not working

I've a nested struct like this
typedef struct Node_link {
struct Node_base *parent, *left, *right;
}Node_link;
typedef struct Node_base {
struct Node_link link[2];
}Node_base;
typedef struct Node{
struct Node_base base;
int size;
int *address;
}Node;
Node_base *head[2] ={NULL, NULL};
//head[0] stores int size and head[1] it's corresponding address
The node has right, left and parent link, all are nested e.g node->left->link.parent=node. I've to maintain all links(parent, left and right) and delete nodes.
I've tried a lot of cases and still missing some. Can someone tell me what all cases I need to use? Or refer me to some material? I searched a lot but no success.
My insert function is as follows:
Node_base * insert(Node_base *location, Node_base *n) {
if (head[0]==NULL)
head[0]=n;
else
{
if (location==NULL){
location=n;
return location;
}
else{
if(((Node *)n)->size < ((Node *)location)->size){
if(location->link[0].left==NULL)
{
location->link[0].left=n;
location->link[0].left->link[0].parent=location;
}
else
location->link[0].left=insert(location->link[0].left,n);
return location;
}
}
And I've the same nested insert function for head[1] which stores the size of node inserted in head[0].
It's hard to tell what's going on here. Your code doesn't look remotely like any BST implementation I've ever seen. Why the need for the Node_Link struct? The pointers in the Node structs should define what the links are. Why the parent pointer? That shouldn't be needed in a standard BST implementation. All you should need is:
struct node {
node *left;
node *right;
void *data;
int size;
};
struct bst {
node *root;
};

Random Queue in C

I've written this code with all correct understandings i have. please check my problems.
#include<stdio.h>
#include<stdlib.h>
// Define a structure for the dequeue elements
This structure is all good, with data, next, previous pointers.
typedef struct RanElmt_ {
void *data;
struct DeqElmt_ *prev;
struct DeqElmt_ *next;
void (*destroy)(void *data);
//Your Code here
} RanElmt;
THis is ok too, acording to what i think is correct.
typedef struct RandQ_{
int size;
struct RanElmt *head;
struct RanElmt *tail;
}RandQ;
RandQ * RandomizedQueue(void (*destroy)(void *data)){
RandQ *relmt = (RandQ*)malloc(sizeof(RandQ));
} // construct an empty randomized queue
int isREmpty(RandQ *rQ){
if ( rQ->size == 0)
return 1;
return 0;
} // is the queue empty?
int rsize(RandQ *rQ){
return rQ->size;
}
// return the number of items on the queue
ACtually this is only one function,(enqueue) I'm going to get the idea and code other functions(dequeue, sample etc..)
int enqueue(RandQ *rQ, const void *data){
RanElmt *relmt = (RanElmt*)malloc(sizeof(RanElmt));
relmt->data = (void*)data;
if (rQ->head == NULL){
relmt = rQ->head;
relmt = rQ->tail;
relmt->prev = NULL;
relmt->next = NULL;
}
else{
rQ->head = relmt;
}
(rQ->head)->prev = relmt;
relmt->prev = rQ->head;
rQ->head = relmt;
} // add the item
main(){
Deque(free);
printf(" okk \n");
}
THis program is giving these errors:
Errors i'm getting
In C struct tags and type names live in different name spaces. That is struct RanElmt and RanElmt are two different types, in addition struct RanElmt is not completely defined.
Your RandQ should be defined something like
typedef struct RandQ_{
int size;
struct RanElmt_ *head; // or RanElmt* head;
struct RanElmt_ *tail; // or RanElmt* tail;
}RandQ;
in addition your RanElmt is probably not what you want, maybe you meant:
typedef struct RanElmt_ {
void *data;
struct RanElmt_ *prev; // pointer to a struct of the same type
struct RanElmt_ *next; // pointer to a struct of the same type
void (*destroy)(void *data);
// You cannot put code here in C (or even a function definition AFAIK).
} RanElmt;
You have confused the struct tag and the typedeffed alias for the queue elements in the definition of the queue:
typedef struct RandQ_{
int size;
struct RanElmt *head;
struct RanElmt *tail;
} RandQ;
Here, the head and tail are of the type struct RanElmt. This struct doesn't exist in your program. You have a struct RanElmt_ (with trailing underscore) that you can also call ´RanElmtwithout thestructkeyword, because you have combined the struct definition with atypedef`.
The compiler still generates the code, because pointers to unknown structs are okay, unless you try to get at their data. Obviously the compiler can't access the struct fields if it doesn't know them.
There's no need for the underscore. The names of structs are in a separate namespace, so you can have both a struct called RandQ and a type (in global namespace) called RanQ. I recommend to use the same name for struct tag and aliassed type.
You can also get rid of the need to use the struct keyword inside the struct defnition if you separate the typedef from the struct definition:
typedef struct RanElmt RanElmt; // use just RanElmt from now on
struct RanElmt {
void *data;
RanElmt *prev;
RanElmt *next;
} RanElmt;
Your code has several other problems, but I think he program is in an early state, so I don't address them here.

C-Void pointer inside a generic list (Contains stucture)

I have 2 different stuctures but i need to contain them in the same generic list.
The structures are :
typedef struct Val1{
int num1;
int num2;
int num3;
}Val1;
typedef struct Val2{
char name[50];
char surname[50];
int ID;
}Val2;
And the list is:
typedef stuct list {
void *value;
struct node *next;
}list;
typedef struct L_head{
node *head;
int num_members;
}L_head;
I need to use the same list implementation but the list needs to handle both of the
strucrure types.I cant figure out how to initialize the list and put some elements in the list .Any advice will be helpfull.
The canonical solution for C would add a common initial field having distinct values to both structures.
typedef struct Val1 {
int discriminator;
int num1;
int num2;
int num3;
} Val1;
typedef struct Val2 {
int discriminator;
char name[50];
char surname[50];
int ID;
} Val2;
If neccessary, you can define a new struct instead.
That has the advantage of preserving the previous layout and alignment guarantees:
struct packed {
int discriminator;
union {struct Val1;struct Val2};
};
Anyway, you could integrate it directly into the node:
typedef stuct node {
struct node *next;
int discriminator; /* You might want to reserve 0 for no content */
union {struct Val1;struct Val2};
} node;
The technical term of the solution is "discriminated union".
You can have a two element array of void pointers - One pointing to struct of type 1 and another to type 2. This should help to get the right structures with the right casting.
If you are able to distinguish between the type of each of the nodes, you could resort to C unions, like in:
typedef struct Val1{
int num1;
int num2;
int num3;
} Val1;
typedef struct Val2{
char name[50];
char surname[50];
int ID;
} Val2;
union {
Val1 val1;
Val2 val2;
} Val;
For adding the list items, you need to cast them to (void*).
In order to determine the type again upon access, you could add another field(enum) to the list, which stores it's type.
I bet this is some training or homework. If C++ is possible:
start using std::list or boost::list implementation.

C union and struct question

I have a tree structure. The nodes would have a leaf node type and internal node type, so I defined these structures, so the internal node would be able to point to either internal nodes or leaf nodes. However, I am having trouble in accessing the child pointers, how can I do that, after all does my code make sense at all?
typedef struct leaf_node_t {
int type;
int key;
int *data_ptr[2]; //This will point to real data.
} leaf_node_t;
typedef struct internal_node_t {
int type;
int key;
typedef union{
struct internal_node_t* iptrs[2];
leaf_node_t* lptrs[2];
} node_ptr;
} internal_node_t;
The typedef of node_ptr does not actually add a field to its enclosing struct. The following adds the fields first, and then follows up with the typedef. The other change I made was having the union represent a single pointer, leaving it to the struct that uses it to decide how many pointers it wants.
typedef struct internal_node_t{
int type;
int key;
union node_ptr_t {
struct internal_node_t* iptr;
leaf_node_t* lptr;
} node_ptr[2];
}internal_node_t;
typedef union node_ptr_t node_ptr_t;
Try this:
typedef struct leaf_node_t{
int key;
int *data_ptr[2];//this will point to real data
} leaf_node_t;
struct internal_node_t;
typedef union{
struct internal_node_t* iptrs[2];
leaf_node_t* lptrs[2];
} node_ptr;
typedef struct internal_node_t{
int key;
node_ptr node;
} internal_node_t;
int main()
{
internal_node_t inode;
leaf_node_t* leaf_node = inode.node.lptrs[0];
return 0;
}
Alternately, if you don't actually need to use the union typedef anywhere else:
typedef struct leaf_node_t{
int key;
int *data_ptr[2];//this will point to real data
}leaf_node_t;
typedef struct internal_node_t{
int key;
union{
struct internal_node_t* iptrs[2];
leaf_node_t* lptrs[2];
}node_ptr;
}internal_node_t;
int main()
{
internal_node_t inode;
leaf_node_t* leaf_node = inode.node_ptr.lptrs[0];
return 0;
}
You should add a flag in the internal_node to know what is the node_ptr, if it's an internal_node_t or a leaf_node_t. Probably a int isInternal[2]; (after the key and before the typedef). if it's 0 the it's internal, if it's 1 then it's leaf_node_t. C language doesn't have a typeof or a GetType to know what type of memory is pointed by a pointer (and C++ has it only if you are compiling with the RTTI "option" activated)

Resources