BIG EDIT:
Ok, my original question didn't help me. Here is a second go.
My struct looks like this:
struct node {
char *name;
int age;
struct node *nextName;
struct node *nextAge;
};
I have to make two linked lists out of structures like this,.
So i have 'rootAges' which keeps track of where the Age-based list starts and
'rootNames' which keeps track of where the names start. I can't seem to get these to update.
that is, i have struct node *rootAges and struct node *rootNames.
I need to pass both of these to a function which adds the elements to the list.
But i also need the roots to change as I add things to the list.
the methods provided so far, haven't changed the value of rootAges for example in the main function, when it is altered in the add function.
Thanks!
You pass the address of a structure's instance to a function that accepts a pointer in C.
void fn(struct data *p)
{
if(p)
p->x = 33;
}
//... main ...
struct data d;
fn(&d);
//d.x == 33
Pass a pointer to the structure.
For example:
typedef struct data{ int x;} s_data;
void foo (s_data* pointer){}
s_data s={0};
foo(&s);
Declaration
void Foo(struct data *);
Definition
void Foo(struct data *p)
{
//body
}
In your code
Foo(root);
Related
i have this piece of code
struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name)
{
struct atmel_tc *tc;
/* Iterate over the list elements */
list_for_each_entry(tc, &tc_list, node) {
/* Do something with tc */
}
[...]
}
this is from a kernel source file, I'm a bit new to C so I'm unable to understand
this line struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name)
as so far I've seen structs declared simply as struct atmel_tc
without any parameters or * , I've seen usages like
struct node {
int data;
struct node *next;
}*head;
where *head is a pointer to an instance of node. Is something similar going on here as well?
could you explain this line or point me towards some documentation for similar kind of syntax
struct atmel_tc *atmel_tc_alloc(unsigned block, const char *name)
This says that atmel_tc_alloc is a function that returns a pointer to a struct atmel_tc and takes as parameters an unsigned named block and a const char * called name.
So I am still pretty new to C programming. I have learned Python though, so I am familliar to some of the codes.
For instance when I create a function in python, I am able to make it general and usable for different classes.
I want to do something similar here. I have two structs which look practically the same. I want to use the same function for both structs, but ofcourse I cant send in the struct name as an argument into the function. What do I do instead?
For now dont worry about what the function does. Its the principle of being able to use two structs in the same function that counts for me. If this is a totally wrong perspective, then I am sorry but this was my first thought when coming upon this problem.
typedef struct{
int number;
struct node *next;
}struct_1;
struct node *head;
typedef struct{
int number;
struct node *next;
}struct_2;
void main()
{
int number1 = 10;
int number2 = 20;
function(number1);
function(number2);
}
void function(int x, struct) // Here is where I want to be able to use 2 different structs for the same function
{
struct *curr, *head;
curr=(node1*)malloc(sizeof(node1));
printf("%d", curr->number);
}
You could have two instances of one structure.
The function can accept either instance and process it as needed.
typedef struct{
int number;
struct node *next;
}mystruct;
void function(int x, mystruct *eachstruct);//prototype
int main()
{
int number1 = 10;
int number2 = 20;
//declare two instances of mystruct
mystruct list_1 = { 0, NULL};
mystruct list_2 = { 0, NULL};
// call the function with one or the other instance of mystruct
function(number1, &list_1);
function(number2, &list_2);
}
void function(int x, mystruct *eachstruct)
{
//do stuff in function
eachstruct->number = x;
if ( eachstruct->next == NULL)
{
//do more stuff
}
}
C does not use duck typing as Python does so you cannot pass one structure that looks like other, completely unrelated structure as if it was this other structure.
Unfortunately C cannot do what you want.
Your options are:
Refactor the code to use the same struct type for all items.
Pass the fields of interest in the structs directly to the functions
Write code to marshal the similar structs to a common struct.
Play fast and loose with the type system and arrange shared elements the same way in the two different structs and cast your pointers.
If you just want a linked list check out how code re-use is achieved in the linux kernel
Answer: No, you cannot do it directly. Welcome to static typing.
There is a way to achieve something similar by using our beloved void * and some castings but, believe me, it is not what you want to do. If you really want to do it ask directly for it. You have been warned.
So I was looking through this C tutorial and I found these lines of code:
struct Monster {
Object proto;
int hit_points;
};
typedef struct Monster Monster;
And I thought that it would make much more sense if it were like this:
typedef struct {
Object proto;
int hit_points;
} Monster;
I could could be totally wrong, because I am very new to C, but I would assume both these pieces of code would do the same thing. So is they do, then is there any reason to prefer one over the other? Or if they are different, what makes them different? Thanks!
The first piece of code defines a type struct Monster, and then gives it another name Monster.
The second piece of code defines structure with no tag, and typedef it as Monster.
With either code, you can use Monster as the type. But only in the first code, you can also use struct Monster.
There are times when the second form won't work. Say you want to create a linked list of Monsters. With the first form, you can add a pointer to the next Monster in the struct.
struct Monster {
Object proto;
int hit_points;
struct Monster* next;
};
You can't do that in the second form since the struct doesn't have a name.
The definitions (from the first part of the question - plus my liberal re-formating):
struct Monster
{
Object proto;
int hit_points;
};
typedef struct Monster Monster;
Is equivalent to:
typedef struct Monster
{
Object proto;
int hit_points;
} Monster;
My preference is:
typedef struct MONSTER_S
{
Object proto;
int hit_points;
} MONSTER_T;
FYI... a struct name isn't required. So if the code only needs to use the type, the following is also fine:
typedef struct
{
Object proto;
int hit_points;
} MONSTER_T;
I have a stack that contains two types of struct. Struct Stud and Struct Prof.
When I want to push something I created two Push functions for both structs. Although I would like it to be with one function but its ok I can bear with it.
Now to Pop. If I want to Pop a student from the Stack, do I have to make a Pop function specifically for Students only? The same with Professors?
How can I store the item if I don't know what type is it? What type must the element be, to store the item there?
Here are the structs:
struct MyStack
{
int head;
void **stack;
int size;
};
typedef struct MyStack STACK;
struct stud
{
char flag;
char fname[50];
int semester;
};
struct prof
{
char flag;
char fname[50];
char course[30];
};
Now to create the Pop function. What do type of item do I pass in the function?
int Pop(STACK *stack,int *head,??? *elem)
{
if(stack->head<=-1)
return 0;
*elem=stack->stack[*head];
*head--;
return 1;
}
You have to encode the type information when you push, simplest is probably to type tag:
#define STUD 0
#define PROF 1
struct stack_entry {
int type;
void *item;
};
struct MyStack
{
int head;
struct stack_entry *stack;
int size;
};
Then change your push functions to attach the right tag when you push. Then, in pop, simplest again is probably to just return a stack_entry struct, and let the calling function figure it out. At that point you might want a snazzier name than "stack_entry" though. Also, it would be slightly preferable to use a union:
struct stack_entry {
int type;
union {
struct stud *stud;
struct prof *prof;
} item;
}
Because then the compiler can help you out a bit, but of course you still have to be more or less as careful as you would be with a void *.
Edit: initialization...
You don't have to mark then end of the buffer with anything, since you have a size variable in the struct. But if you wanted to do that I would have that be its own type
#define END_OF_BUFFER 1
#define STUD 2
#define PROF 3
And then for init you could do:
stack->size = size;
stack->stack = calloc(sizeof(*stack->stack), size + 1);
stack->stack[size].type = END_OF_BUFFER;
stack->head=-1;
Though I tend to use "head" to refer to a pointer that points to the next place to write to, but I'm not sure how standard that is. But the buffer is an array of strack_entries, not void *'s.
typedef struct node{
int term;
struct node *next;
}node;
typedef void(*PTR )(void *);
typedef void(*PTR1)(void *,int,int);
typedef int(*PTR2)(void *,int);
typedef void(*PTR3)(void *,int);
typedef void(*PTR4)(void *,void *,void *);
typedef struct list{
node *front,*rear;
PTR3 INSERT;
PTR *MANY;
PTR DISPLAY,SORT,READ;
PTR4 MERGE;
}list;
void constructor(list **S)
{
(*S)=calloc(1,sizeof(list));
(*S)->front=(*S)->rear=NULL;
(*S)->INSERT=push_with_value;
(*S)->READ=read;
(*S)->SORT=sort;
(*S)->DISPLAY=display;
(*S)->MERGE=merger;
(*S)->MANY=calloc(2,sizeof(PTR));
(*S)->MANY[1]=read;
}
int main()
{
list *S1,*S2,*S3;
constructor(&S1);
constructor(&S2);
constructor(&S3);
S1->MANY[1](S1);
S1->SORT(S1);
S1->DISPLAY(S1);
return 0;
}
The void * parameter in all such functions gets typecast to list * inside the function.
Is there any way through which I can call S1->READIT; by changing the MANY[1] to another name like READ_IT;?
I intend to create a common header file, so that I can use it for all my programs.
Since I don't know how many function pointers I will need I intend to create a dynamic array of each function pointer type.
typedef struct list{
node *front,*rear;
PTR3 INSERT;
PTR READIT;
PTR DISPLAY,SORT,READ;
PTR4 MERGE;
}list;
...
(*S)->READIT = read;
...
S1->READIT(S1);
Take a look at the Linux kernel implementation of (doubly linked) lists, as defined here (and following/referenced files). They are used all over the place. Most of the manipulation is done in macros to e.g. run an operation on all nodes of the list.
If what you are trying to define is getting too complicated, step back and look for simpler alternatives. Don't generalize beforehand; if the generalization isn't used it is a waste; if something (slightly) different is later needed, it is a poor match that requires workarounds or even reimplementation.
Take a look at the interfaces exposed by the C++ STL list, those folks have thought long and hard on the matter (in a different setting, though).
Or just bite the bullet and use C++ if you want full-fledged OOP.