Returning a nested structure from a function - c

I am writing code in which I want to return a nested structure. I wonder how to do that.
static int ORDERID = 0;
struct item
{
struct data
{
int orderid;
char content[10][20];
} details;
struct node *next;
};
typedef struct item product;
So insertion of a new product contains two parts:
details structure
pointer pointing to next product
In the details structure I have to have different types of product description, say:
Shoes with its orderid, and other details in the array of strings (char content[10][10])
Shirt with its orderid, and other details in the array of strings (char content[10][10])
So for the insertion of a new product I need a function to return a details structure i.e the nested structure of the product.
How to do that?

Well, you can actually define the struct data outside of the struct item and then use struct data to define a variable details inside of struct item. That is,
struct data {
int orderid;
char content[10][20];
};
struct item {
struct data details;
struct item *next;
}
And, then you can freely return a struct data object from a function.
EDIT :
If you want to create a function which can return a struct data object you can probably do the following :-
struct data * function_data() {
struct data *someData;
someData->orderid = 16;
someData->content[0] = "Shoes";
return someData;
}
I hope this adds further quality to the answer.

You can use struct data as the return type of a function

Related

Structures in C with "no member named..." error

I'm trying to create a struct which contains the country, state, city and the name of a local shop. Unfortunately, I get this error:
No member named bavaria in struct country
So it seems that the error occurs here:
strcpy(germany.bavaria.ingolstadt.westpark, "Westpark");
What am I doing wrong?
This is my complete code:
#include <stdio.h>
#include <string.h>
int main() {
struct country {
char countryname[100];
struct state {
char statename[100];
struct city {
char cityname[100];
int postal;
struct shop {
char shopname[100];
} shop;
} city;
} state;
} country;
struct country germany;
struct state bavaria;
struct city ingolstadt;
struct shop westpark;
strcpy(germany.countryname, "Germany");
strcpy(germany.bavaria.ingolstadt.westpark, "Westpark");
return 0;
}
Let's separate the definitions out from where they're used to make it easier to read:
struct shop {
char shopname[100];
};
struct city {
char cityname[100];
int postal;
struct shop shop;
};
struct state {
char statename[100];
struct city city;
};
struct country {
char countryname[100];
struct state state;
};
Now you have:
struct country germany;
struct state bavaria;
struct city ingolstadt;
struct shop westpark;
strcpy(germany.bavaria.ingolstadt.westpark, "Westpark");
Here's the issue: struct country does not have a member called bavaria. It only has a member called state. What you want is:
strcpy(germany.state.city.shop.shopname, "Westpark");
What you probably really want is this:
struct country germany;
strcpy(germany.countryname, "Germany");
strcpy(germany.state.statename, "Bavaria");
strcpy(germany.state.city.cityname, "Ingolstadt");
strcpy(germany.state.city.shop.shopname, "Westpark");
When you write struct Y in this context
struct X {
struct Y {
int z;
} y;
} x;
you do two things:
Define struct Y, and
Add field y of type struct Y inside struct X.
The four structs that you define are independent of each other. Each of your structs defines a single shop, because there are no collections inside your struct country.
Here is how you can define your shop using the structures that you defined:
// This is what the structure dictates, probably not what you want
struct country westpark;
strcpy(westpark.countryname, "Germany");
strcpy(westpark.state.statename, "Bavaria");
strcpy(westpark.state.city.cityname, "Ingolstadt");
strcpy(westpark.state.city.shop.shopname, "Westpark");
This does not look like anything that you may want, though. I think you were looking for something like this:
struct country {
char countryname[100];
struct state {
char statename[100];
struct city {
char cityname[100];
int postal;
struct shop {
char shopname[100];
} shop[MAX_SHOP]; // maybe 128
int shopCount;
} city[MAX_CITY]; // Around 256
int cityCount;
} state[MAX_STATE]; // Probably 16
int stateCount;
} country;
The idea here is to construct a country as an array of states, a state as an array of cities, and a city as an array of shops. Each level of this hierarchy also stores a count of items in its level, i.e. stateCount counts how many elements of the state[] array have been filled, cityCount in each state[] stores the number of city[] elements that have been filled, and so on.
The size of this struct is going to be about 50MB, so do not make it an automatic local variable: it should be either an outer scope-static or a function-scope static, because 50 MB is too much of a stack space on most systems. Here is how you would add your shop to this struct:
strcpy(country.countryname, "Germany");
country.stateCount = 1; // For Bavaria
strcpy(country.state[0].statename, "Bavaria");
country.state[0].cityCount = 1; // For Ingolstadt
strcpy(country.state[0].city[0].cityname, "Ingolstadt");
country.state[0].city[0].shopCount = 1; // for Westpark
strcpy(country.state[0].city[0].shop[0].shopname, "Westpark");
Note that this is extremely inefficient, because it pre-allocates everything at the max. Hence the elements of the state[] array representing Bremen and Bavaria would end up with the same number of pre-allocated city[] elements, even though Bavaria is a lot larger, and probably needs more city entries. To deal with this in a resource-efficient way you would need to use dynamic memory allocation.
The variables bavaria, ingolstadt, and westpark are separate items, not members of the country struct.
strcpy(germany.state.city.shop.shopname, "Westpark");
might work (but perhaps not do what you intend).
Based on how your struct is currently defined, you would need to do this:
strcpy(germany.countryname, "Germany");
strcpy(germany.state.statename, "Bavaria");
strcpy(germany.state.city.cityname, "ingolstadt");
strcpy(germany.state.city.shop.shopname, "Westpark");
A better way to define the struct would be like this:
struct shop {
char countryname[100];
char statename[100];
char cityname[100];
int postal;
char shopname[100];
};
Then you could do this:
struct shop myshop;
strcpy(myshop.countryname, "Germany");
strcpy(myshop.statename, "Bavaria");
strcpy(myshop.cityname, "ingolstadt");
strcpy(myshop.shopname, "Westpark");
You have defined four independent structs. They are not linked with each other.
You now can do
strcpy(germany.state.city.shop, "Westpark");
or
strcpy(westpark, "Westpark");
In general, struct member names are compile time things. They are resolved to address offsets by the compiler. You city/state/shop names are runtime data. You cannot use them as struct members.
Also you apparently want to model a 1:n relation. I think you need a different data structure, like e.g. a hash.

Struct Confusion in C

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;

C: struct with one less field. How do I declare/use it efficiently?

Assume we have two different struct that have mostly common fields but one or two different fields or less fields. For example:
typedef struct HobbyNodetag {
char *name; // hobby name
struct HobbyNodetag* link; // link to next HobbyNode
int count; // number of times this hobby was mentioned by user
// more fields...
// but identical type/variable name with MyHobbyList
} HobbyNode; // database of entire hobby node; singly linked list
typedef struct MyHobbyTag{
char *name; // hobby name
struct MyHobbyTag* link; // linked to next MyHobbyNode
// more fields...
// but identical type/variable name with EntireHobbyList
} MyHobbyNode; // single person's hobby node; singly linked list
Do we have more efficient/elegant coding practice to use above two structs? Wouldn't this be a waste of having two different structs as they share majority of the fields?
UPDATE
My earlier question was misleading. The above example is the node and singly linked (by link).
You can move all the extra fields (which are present in the second struct but not in the first one) to the end of the struct type definition, then use the smaller struct as the "base" of the bigger one:
struct BaseFoo {
int count;
char name[128];
float value;
};
struct ExtendedFoo {
struct BaseFoo base;
struct ExtendedFoo *next;
};
What is nice about this solution is that you can have "polymorphism": since the C standard guarantees that there is no padding before the first struct member in memory, this will work just fine:
void print_name(struct BaseFoo *foo)
{
printf("Count: %d\n", foo->count);
printf("Name: %s\n", foo->name);
}
struct ExtendedFoo foo = { /* initialize it */ };
print_name((BaseFoo *)&foo);
You can do something like this, but I believe that's not what you're after.
typedef struct myHobbyTag{
char *name;
struct myHobbyTag* link;
} MyHobbyList;
typedef struct entireHobbytag {
MyHobbyList commonPart;
int count;
} EntireHobbyList;
If you move all of the common fields to the top, you can declare a base class and an inheriting class using OOP in C (search for it on StackOverflow.)
There are basically two ways to do this.
You declare a base class, then in the inheriting class (which has more fields) you put the base class as a member at the top of the inheriting class.
struct hobbyLink; // common link
typedef struct baseHobbytag {
char *name;
struct hobbyLink* link;
} BaseHobby;
typedef struct myHobbyTag{
BaseHobby hobby;
int count;
// more fields...
} HobbyTag;
You use a #define for all of the common base members, and put that #define in all inheriting classes.
#define BASEHOBBY_MEMBERS \
char *name; \
struct hobbyLink* link;
// base class
typedef struct baseHobbytag {
BASEHOBBY_MEMBERS
} BaseHobby;
// Inherit basehobby
typedef struct myHobbyTag{
BASEHOBBY_MEMBERS
int count;
// more fields...
} HobbyTag;

Combining two structures into new one on C?

So, we have an interesting situation.
We are supposed to write a DBMS in C under Linux and we have the following problem:
when trying to join two relations/tables the new relation/table has number of Fields/Columns equal to the sum of both joining relations/tables. This is fine, but when we have to copy the data of the tuple/row from the two joining relations/tables we don't seem to find a way. The tuples/rows are realized as list elements via this structure:
typedef struct element {
void *data;
struct element *next;
} Element;
The new element is created via this function:
Element *
newElement (void *data)
{
Element *e = (Element*) malloc (sizeof (Element));
assert (e != NULL);
e->data = data;
e->next = NULL;
return e;
}
And the *data parameter is passed as of this type:
typedef struct {
int sid;
char sname[STRLEN];
int rating;
float age;
} Sailor;
The thing is when we have to join two relations we cannot know what Structure they use for their tuples/rows and therefore we cannot create the new tuples/rows for the new relation from the tuples/rows of the two joining relations.
Please help.
Given you cannot at runtime define new structures, something like the following (hack?) could work..
Firstly define a base structure which only has a type id
typedef struct
{
int type_id; /* this holds a number which identifies the following structure */
} TypeID;
/* now all structures should contain this */
typedef struct {
TypeID type;
char sname[STRLEN];
int rating;
float age;
} Sailor;
typedef struct {
TypeID type;
char sname[STRLEN];
int sailors;
} Boat;
Now treat the data segment as a container of these structs, let's say for example that I will have two structs in data (i.e. joined the two above structs), my data segment would look like:
----------
| Sailor |
+--------+
| Boat |
----------
When reading the data chunk, first cast it to TypeID, which gives you the type, then you can cast it to the real structure. Then if there is more data in the data segment, move the pointer by the sizeof the structure you've just read, and again do the same process. Basically this allows you to have a variable length segment which is a set of structures of different types - i.e. your joined data structure.
Oh, and you'll need to modify your Element structure to hold the size of the data segment as well.

Pass a dynamic structure by reference? [C]

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);

Resources