I have the following structs:
struct mtmFlix_t {
List usersList;
List seriesList;
};
struct User_t {
int age;
char* username;
MtmFlix mtmFlix;
};
These are the typedefs in list.h :
typedef void* ListElement;
typedef ListElement(*CopyListElement)(ListElement);
typedef void(*FreeListElement)(ListElement);
These are the typedefs in user.h and MtmFlix.h :
typedef struct User_t *User;
typedef struct mtmFlix_t* MtmFlix;
I would like to use the following function in mtmflixCreate, but I can't seem to figure out how to cast the UserCreate and UserFree to (*void) ?
List listCreate(CopyListElement copyElement, FreeListElement freeElement);
MtmFlix mtmFlixCreate()
{
MtmFlix newMtmFlix = malloc(sizeof(*newMtmFlix));
if (newMtmFlix == NULL) {
return NULL;
}
newMtmFlix->seriesList=listCreate(?????);
newMtmFlix->usersList=listCreate(?????);
}
The following functions appear in user.h :
User UserCreate(MtmFlix mtmFlix, const char* username,int age);
Void UserFree(User user);
You don't. You have to create functions that have the needed types. Something like this:
ListElement CopyUserListElement(ListElement elem) {
// (ListElement) is not necessary here, but included for completeness
return (ListElement)CopyUser((User_t*)elem);
}
void FreeUserListElement(ListElement elem) {
UserFree((User_t*)elem);
}
Related
Is there any way, whether union, struct, or something else, to have a group of functions?
typedef struct {
//ERROR
int sqr(int i) {
return i * i;
}
//ERROR
int cube (int i) {
return i * i * i;
}
} test;
Fields in structs can be function pointers:
struct Interface {
int (*eval)(int i);
};
You cannot define the functions in the struct body, but you can assign functions with the same signature to the struct fields:
int my_sqr(int i) {
return i * i;
}
int my_cube(int i) {
return i * i * i;
}
struct Interface squarer = { my_sqr };
struct Interface cuber = { my_cube };
Then call the fields like a normal function:
printf("%d\n", squarer.eval(4)); // "16"
printf("%d\n", cuber.eval(4)); // "64"
I'm beginner in C programming and I have a doubt about to pass a generic struct to a function in C.
Here is what I have:
typedef struct {
char name[20];
float price;
} product;
typedef struct {
char name[20];
int type;
} category;
And I want to do something like this:
void changeName(struct *s, newName[20]) {
strcpy(s->name, newName);
}
If someone has already asked that, please disconsider this and sends me the issue link.
Someone can help me?
Thanks.
Using a union
One approach would be to add a structure containing a union, itself containing pointers to product and category structures, as well as an enum to identify the type of data in the struct. This union, or a pointer to it, could be passed to a change_name() function.
Here is an example that would work in C11. It uses an unnamed union member, so this is not valid C99 code:
#include <stdio.h>
#include <string.h>
typedef struct {
char name[20];
float price;
} product;
typedef struct {
char name[20];
int type;
} category;
typedef struct {
enum { PRODUCT, CATEGORY } type;
union {
product *prod;
category *cat;
};
} generic;
void change_name(generic *gen, const char *new_name);
int main(void)
{
product prod_a = { .name = "widget", .price = 1.99 };
category cat_a = { .name = "general", .type = 1 };
generic gen_prod_a = { .type = PRODUCT, .prod = &prod_a };
generic gen_cat_a = { .type = CATEGORY, .cat = &cat_a };
printf("prod_a.name = %s\n", prod_a.name);
printf("cat_a.name = %s\n", cat_a.name);
change_name(&gen_prod_a, "gadget");
change_name(&gen_cat_a, "specific");
printf("prod_a.name = %s\n", prod_a.name);
printf("cat_a.name = %s\n", cat_a.name);
return 0;
}
void change_name(generic *gen, const char *new_name)
{
switch (gen->type) {
case PRODUCT:
strcpy(gen->prod->name, new_name);
break;
case CATEGORY:
strcpy(gen->cat->name, new_name);
break;
default:
fprintf(stderr, "Unknown type in change_name()\n");
}
}
This could be made to work in C99 by naming the union:
typedef struct {
enum { PRODUCT, CATEGORY } type;
union {
product *prod;
category *cat;
} data; // named for C99
} generic;
/* ... */
generic gen_prod_a = { .type = PRODUCT, .data.prod = &prod_a };
generic gen_cat_a = { .type = CATEGORY, .data.cat = &cat_a };
/* ... */
void change_name(generic *gen, const char *new_name)
{
switch (gen->type) {
case PRODUCT:
strcpy(gen->data.prod->name, new_name);
break;
case CATEGORY:
strcpy(gen->data.cat->name, new_name);
break;
default:
fprintf(stderr, "Unknown type in change_name()\n");
}
}
Alternatively, one struct type could hold an enum identifier and a union containing the product and category structures. This approach may seem a bit more streamlined:
#include <stdio.h>
#include <string.h>
typedef struct {
enum { PRODUCT, CATEGORY } type;
union {
struct {
char name[20];
float price;
} prod;
struct {
char name[20];
int type;
} cat;
} data;
} record;
void change_name(record *rec, const char *new_name);
int main(void)
{
record prod_a = { .type = PRODUCT };
change_name(&prod_a, "widget");
prod_a.data.prod.price = 1.99;
record cat_a = { .type = CATEGORY };
change_name(&cat_a, "general");
cat_a.data.cat.type = 1;
printf("prod_a.name = %s\n", prod_a.data.prod.name);
printf("cat_a.name = %s\n", cat_a.data.cat.name);
change_name(&prod_a, "gadget");
change_name(&cat_a, "specific");
printf("prod_a.name = %s\n", prod_a.data.prod.name);
printf("cat_a.name = %s\n", cat_a.data.cat.name);
return 0;
}
void change_name(record *rec, const char *new_name)
{
switch (rec->type) {
case PRODUCT:
strcpy(rec->data.prod.name, new_name);
break;
case CATEGORY:
strcpy(rec->data.cat.name, new_name);
break;
default:
fprintf(stderr, "Unknown type in change_name()\n");
}
}
Using a type-generic macro
Both of the above approaches are a little bit awkward. Another solution, available for C11 only, is to use the _Generic keyword in a type-generic macro. Here, functions are written for each expected data type, and a macro selects which function definition is to be used based on type. A virtue of this approach is that as new types are added, only new functions and updates to the type-generic macro are needed to handle them.
#include <stdio.h>
#include <string.h>
#define change_name(S, N) _Generic ((S), \
prod_ptr: change_name_prod, \
cat_ptr: change_name_cat \
)((S), (N))
typedef struct {
char name[20];
float price;
} product;
typedef struct {
char name[20];
int type;
} category;
typedef product *prod_ptr;
typedef category *cat_ptr;
void change_name_prod(product *prod, const char *new_name);
void change_name_cat(category *cat, const char *new_name);
int main(void)
{
product prod_a = { .name = "widget", .price = 1.99 };
category cat_a = { .name = "general", .type = 1 };
printf("prod_a.name = %s\n", prod_a.name);
printf("cat_a.name = %s\n", cat_a.name);
change_name(&prod_a, "gadget");
change_name(&cat_a, "specific");
printf("prod_a.name = %s\n", prod_a.name);
printf("cat_a.name = %s\n", cat_a.name);
return 0;
}
void change_name_prod(product *prod, const char *new_name)
{
strcpy(prod->name, new_name);
}
void change_name_cat(category *cat, const char *new_name)
{
strcpy(cat->name, new_name);
}
All of the above programs have the same output:
prod_a.name = widget
cat_a.name = general
prod_a.name = gadget
cat_a.name = specific
You have already typedef-ed the structures. You can use these other names.
For example, if the name is product, first create a variable and call the function
product var={"name", 1.2};
changeName(&var, "AnotherName");
Then pass this variable to a function
void changeName(product *s, char newName[])
{
strcpy(s->name, newName);
}
Generic programming, which implies type-safety just doesn't really exist in C. But there are ways around that.
What I understand from your question, is 'Can I define a function that can be applied to common elements of different structures?
Let's expand you example a bit, to have items which share a common trait.
struct info
{
char name[20];
int id;
};
struct product
{
Info info;
int price;
};
struct category
{
Info info;
int type;
};
You can now define a function that would work safely on the traits shared by both product and category.
void changeName(info* p, const char* name)
{
strcpy_s(info->name, sizeof(info->name), name);
}
int main()
{
category cat;
product prod;
memset(&cat, 0, sizeof(cat));
memset(&prod, 0, sizeof(prod));
changeName(&cat.info, "Category 1");
changeName(&prod.info, "blue product");
return 0;
}
I've been struggling with this for a while, I can't seem to create a valid LinkedList data structure in C,
Here's all my structures:
typedef struct {
int size;
int *cellsI;
int *cellsJ;
} DataInList;
typedef struct listElement{
DataInList dataVar;
struct listElement *next;
} LinkedListElement;
typedef struct {
LinkedListElement*first;
LinkedListElement*last;
} LinkedListRoot;
I have a function that adds a data element to the linked list:
public void addDataToList(LinkedListRoot root, DataInList data) {
LinkedListElement newElem;
newElem.dataVar = data;
newElem.next = NULL;
if(root->first == NULL) {
root->first = &newElem;
root->last = &newElem;
} else {
root->last->next = &newElem;
root->last = &newElem;
}
}
Can anyone help me please?
As the commenter said, you've defined newElem in the function, and on the stack as well, so you have no way to globalize it or return a permanent entry to it. Something more along these lines. I haven't tested it yet, but it should give you the idea:
typedef listData struct {
int size;
int *cellsI;
int *cellsJ;
} listData_t
typedef struct listElement {
listData_t dataVar;
struct listElement *next;
} listElement_t;
typedef struct listRoot {
listElement_t *first;
listElement_t *last;
} listRoot_t;
listElement_t *
addDataToList(listRoot_t *root, listData_t *data) {
listElement_t *newElem = malloc(sizeof(struct listElement));
if (newElem == NULL) {
fprintf(stderr, "Error allocating memory\n");
exit(-1)
}
newElem->dataVar = data;
newElem->next = NULL;
if (root->first == NULL) {
root->first = newElem;
root->last = newElem;
} else {
root->last->next = newElem;
root->last = newElem;
}
return newElem;
}
In chasing down a very opaque bug, I have been trying to compile with no warnings or errors. This part of my code worked fine, but gcc complains about the braces--it says there are braces missing and extra braces. I usually initialise a bit more sloppily but here I'm being as pedantic as possible with braces for each logical level of inclusion. The only struct I really care about initialising is the last one, the Ccfg. I thought I'd build up to it gradually as it contains nested other structs, but apparently even the ones preceding it are mis-initialized according to gcc.
Here's the code:
#define max_nodes 24
struct Cseg
{
int begin;
int arc;
int end;
};
struct Node
{
struct Cseg exit[4];
};
struct Core
{
int num_circles;
int num_nodes;
struct Node node[max_nodes];
};
struct Ccfg
{
struct Core core;
int dummy1;
int dummy2;
};
int main(void)
{
struct Cseg A = {0,1,2};
struct Node B =
{
{0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1}
};
struct Node C =
{
{0,1,2}, {1,3,0}
};
struct Core D =
{4, 4,
{
{ {0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1} },
{ {1,3,0}, {2,1,0}, {3,-2,1}, {2,-1,0} },
{ {3,1,2}, {0,1,2}, {1,-3,0}, {2,-3,1} }
}
};
struct Ccfg E =
{
{2, 2,
{
{ {0,1,1}, {0,2,1} },
{ {1,2,0}, {1,1,0} }
}
}
};
return 0;
}
Some of the initialisations are incomplete; that is deliberate. My real ccfg struct has many more fields but I've simplified it for this post. If someone could let me know what I'm doing wrong I'd appreciate it a lot. Thanks!
EDIT: in my working code, the initialiser for struct Ccfg E omits the innermost braces, and works fine (but gcc still warns me about it). I added them into this test because they seemed logically appropriate, but they actually generate an error--which I don't understand.
You are missing braces in some places. Specifically, if you have an array of structs, the entire array needs to be brace-wrapped; you were just wrapping each struct entry. I just added braces as needed and it works fine now. http://ideone.com/fork/HqxB9R
#define max_nodes 24
struct Cseg
{
int begin;
int arc;
int end;
};
struct Node
{
struct Cseg ex[4];
};
struct Core
{
int num_circles;
int num_nodes;
struct Node node[max_nodes];
};
struct Ccfg
{
struct Core core;
int dummy1;
int dummy2;
};
int main(void)
{
struct Cseg A = {0,1,2};
struct Node B =
{
{ {0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1} }
};
struct Node C =
{
{ {0,1,2}, {1,3,0} }
};
struct Core D =
{4, 4,
{
{ { {0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1} } },
{ { {1,3,0}, {2,1,0}, {3,-2,1}, {2,-1,0} } },
{ { {3,1,2}, {0,1,2}, {1,-3,0}, {2,-3,1} } }
}
};
struct Ccfg E =
{
{2, 2,
{
{ { {0,1,1}, {0,2,1} } },
{ { {1,2,0}, {1,1,0} } }
}
}
};
return 0;
}
I have declared typedef void (*DoRunTimeChecks)();
How do I store that as a field in a struct? How do I assign it? How do I call the fn()?
Just put it in like you would any other field:
struct example {
int x;
DoRunTimeChecks y;
};
void Function(void)
{
}
struct example anExample = { 12, Function };
To assign to the field:
anExample.y = Function;
To call the function:
anExample.y();
#include <stdio.h>
typedef void (*DoRunTimeChecks)();
struct func_struct {
DoRunTimeChecks func;
};
void function()
{
puts("hello");
}
int main()
{
struct func_struct func_struct;
func_struct.func = function;
func_struct.func();
return 0;
}