Expected specifier-qualifier-list before 'rooms' - c

I'm working on a DnD-Text-Based-Style C game, and I'm having a problem compiling my structure.
Here is what I have for a structure so far:
typedef struct stats { //
int strength; //
int wisdom; //
int agility; //
} stats;
typedef struct rooms {
int n_monsters;
int visited;
rooms nentry;
rooms sentry;
rooms wentry;
rooms eentry;
monster *monsters;
} rooms;
typedef struct monster {
int difficulty;
char *name;
char *type;
int hp;
} monster;
typedef struct dungeon {
char *name;
int n_rooms;
rooms *rooms;
} dungeon;
typedef struct player {
int maxhealth;
int curhealth;
int mana;
char *class;
char *condition;
stats stats;
rooms c_room;
} player;
typedef struct game_structure {
player p1;
dungeon d;
} game_structure;
When I compile it, I get the error:
structure.h:21: error: specifier-qualifier-list before 'rooms'
Can you help me figure out why this is? Is it because I'm calling rooms from the structure that contains rooms? Please help.

There are many many problems with this piece of code. The first is that a struct definition must know how much memory to allocate, and it cannot do this when it contains a type that has not been fully defined (this is why people recommend that you use a pointer, since the size of a pointer is known at compile time).
However, and this is important, simply changing to pointers will not solve the problem, since the first room* is encountered before the appropriate typedef completes. You would need to write something like:
struct rooms {
int n_monsters;
int visited;
struct rooms *nentry;
struct rooms *sentry;
struct rooms *wentry;
struct rooms *eentry;
monster *monsters;
} rooms;
or perform a forward declaration (typedef struct rooms rooms;). You also need to make sure the monster type is defined or at least has a forward declaration.

You can't have a variable with the same name as a type. Your dungeon structure has this field entry:
rooms *rooms;
Change that variable name (or, alternatively, rename the type) to something else. What you have now is analogous to:
int int;
Which is clearly not going to work!

typedef struct rooms {
int n_monsters;
int visited;
rooms nentry;
rooms sentry;
rooms wentry;
rooms eentry;
monster *monsters;
} rooms;
Looks like rooms is a recursive type, you certainly wanted to use pointers instead:
typedef struct rooms rooms;
struct rooms {
int n_monsters;
int visited;
rooms *nentry;
rooms *sentry;
rooms *wentry;
rooms *eentry;
monster *monsters;
} rooms;

Related

Multiple structure pointers inside another structure

I am writing code to create a team of players
struct player {
char name[32];
double avg;
};
struct team {
char teamname[32];
player *players[11];
};
I get the error:
A4.c:31:3: error: unknown type name ‘player’
player *players[11];
I've looked elsewhere on the internet and I can't seem to find out how I would store multiple player pointers inside the team structure?
struct player {
char name[32];
double avg;
};
In the above code, player is a struct name, not a type. So the correct definition of team is:
struct team {
char teamname[32];
struct player *players[11];
};
Alternatively, you can define a new player type:
typedef struct player {
char name[32];
double avg;
} player;
struct team {
char teamname[32];
player *players[11];
};
Note: In C++, the struct keyword is optional before in declaration of a variable. In C, it is mandatory. (https://www.geeksforgeeks.org/structures-in-cpp/)

Initializing pointers of structs through malloc

This is my following structs:
struct team {
char* group_name;
Driver driver1;
Driver driver2;
} ;
struct season {
int year;
int groupNums;
Team *teamArray;
int numOfDrivers;
Driver *driverArray;
};
this is how I initialized them each suitable header
typedef struct season* Season;
typedef struct team* Team;
I initialized the teamArray like this
season1->teamArray = (Team *)malloc(sizeof(Team)*teamNums);
ps: season1 is an input of type Season
Is this the right way to do it?

Create a list of structs the same size as another list in C

I have a list of students ordered for their registration number in C:
typedef struct student_type_ {
int number;
char name[20];
char surname[20];
struct stud_type_ *next_student;
} student_type;
and now I want to make another list of pointers to the elements of that list, that orders it alphabetically considering the name.
typedef struct sort_list_ {
struct student_type_ *student_data;
struct sort_list *next_student;
} sort_list;
Therefore I thought on first creating a new sort_list with the same size as student_type, but I don't get it right... is there a simple and elegant way to do this in C?
As a general design rule, always separate the data from the presentation of data. This will make your code cleaner and more elegant.
My suggestion: Make a student_data structure which contains only the student information. Then create two separate lists - one to sort by registration number and another to sort by name.
typedef struct student_data_ {
int number;
char name[20];
char surname[20];
} student_data;
typedef struct sorted_student_list_ {
struct student_data_ *student;
struct sorted_student_list_ *next;
} sorted_student_list;
...
sorted_student_list sorted_students_by_reg_number;
sorted_student_list sorted_students_by_name;

Pointer to struct within different struct. C

I am currently working on a text based game in C and I'm having a problem altering values when certain events happen. Here is some of my data structure code:
typedef struct player {
int maxhealth;
int curhealth;
int in_combat;
monster c_enemy;
char *class;
char *condition;
rooms c_room;
inventory i;
stats stats;
} player;
Now, I think my problem is that I currently have c_room (Current Room) as a rooms, instead of a pointer to a rooms. This affects me later because I need to alter things like n_monsters within the struct rooms for the current room. However, when I modify it by doing p.c_rooms.n_monsters -= 1; I'm not sure it alters the actual value of n_monsters for the room that I should be referring to. I've tested this by leaving a room when n_monsters is 0, and then coming back to see that it's back at 1, the default value.
So yea, how would I point to right room?
Just:
typedef struct player {
int maxhealth;
int curhealth;
int in_combat;
monster c_enemy;
char *class;
char *condition;
rooms *c_room; // Like this?
inventory i;
stats stats;
} player;
// And then the assignment would look like:
c_room = *rooms[3]; <- an array of rooms for the dungeon in the game.
Assuming that c_room is a plain struct and not a pointer then you are right.
If you have
struct A {
int v;
};
struct B {
struct A a;
}
A a;
a.v = 3;
B b;
b.a = a;
This will actually copy the content of a inside B.a since they are assigned by value. They will be two different A, any modification to one of them won't be reflected on the other.
In your situation I would do something like:
struct Room {
// whatever
}
struct Room rooms[MAX_ROOMS];
struct Player {
struct Room *room;
}
Player p;
p.room = &rooms[index];
Now you will be able to correctly reference to room by p->room, it will be just a pointer to the actual room.

Resolve circular typedef dependency?

What is the best way to resolve the following circular dependency in typedef-ing these structs?
Note the C language tag - I'm looking for a solution in standard gcc C.
typedef struct {
char* name;
int age;
int lefthanded;
People* friends;
} Person;
typedef struct {
int count;
int max;
Person* data;
} People;
The answer lies in the difference between declaration and definition. You are attempting to declare and define in the same step (in the case of a new type via typedef). You need to break these up into different steps so the compiler knows what you are talking about in advance.
typedef struct Person Person;
typedef struct People People;
struct Person {
char* name;
int age;
int lefthanded;
People* friends;
};
struct People {
int count;
int max;
Person* data;
};
Note the addition of the two 'empty' typedefs at the top (declarations). This tells the compiler that the new type Person is of type 'struct Person' so that when it sees that inside the definition of struct People it knows what it means.
In your particular case, you could actually get away with only predeclaring the People typdef because that is the only type used before it is defined. By the time you get into the definition of struct People, you have already fully defined the type Person. So the following would also work but is NOT RECOMMENDED because it is fragile:
typedef struct People People;
typedef struct {
char* name;
int age;
int lefthanded;
People* friends;
} Person;
struct People {
int count;
int max;
Person* data;
};
If you swap the order of the structure definitions (moving struct People above the typedef of Person) it will fail again. That's what makes this fragile and, therefore, not recommended.
Note that this trick does NOT work if you include a struct of the specified type rather than a pointer to it. So, for example, the following WILL NOT compile:
typedef struct Bar Bar;
struct Foo
{
Bar bar;
};
struct Bar
{
int i;
};
The above code gives a compiler error because the type Bar is incomplete when it tries to use it inside the definition of struct Foo. In other words, it doesn't know how much space to allocate to structure member 'bar' because it hasn't seen the definition of struct bar at that point.
This code will compile:
typedef struct Foo Foo;
typedef struct Bar Bar;
typedef struct FooBar FooBar;
struct Foo
{
Bar *bar;
};
struct Bar
{
Foo *foo;
};
struct FooBar
{
Foo foo;
Bar bar;
FooBar *foobar;
};
This works, even with the circular pointers inside Foo and Bar, because the types 'Foo' and 'Bar' have been pre-declared (but not yet defined) so the compiler can build a pointer to them.
By the time we get to defining FooBar, we have defined how big both Foo and Bar are so we can include the actual objects there. We can also include a self-referential pointer to type FooBar because we have pre-declared the type.
Note that if you moved the definition of struct FooBar above the definitions of either struct Foo or Bar, it would not compile for the same reason as the previous example (incomplete type).
Forward-declare one of the structs:
struct people;
typedef struct {
/* same as before */
struct people* friends;
} Person;
typedef struct people {
/* same as before */
} People;
As for readability :
typedef struct Foo_ Foo;
typedef struct Bar_ Bar;
struct Foo_ {
Bar *bar;
};
struct Bar_ {
Foo *foo;
};
It might be a good idea to avoid typedef struct altogether;
Since Person just wants a pointer to People, it should be fine to just predeclare the latter:
typedef struct People People;
Then change the second declaration to just declare using the struct tag, like so:
struct People {
int count;
int max;
Person data[];
};
struct _People;
typedef struct {
char* name;
int age;
int lefthanded;
struct _People* friends;
} Person;
struct _People {
int count;
int max;
Person data[1];
};
Note: Is Person data[]; standard?
struct People_struct;
typedef struct {
char* name;
int age;
int lefthanded;
struct People_struct* friends;
} Person;
typedef struct People_struct {
int count;
int max;
Person data[];
} People;

Resources