Using Structs in C - c

Hi im building a simple game in c (im new to the language). Im using the following structs:
typedef struct
{
int adjacent_mines;
bool revealed;
bool is_mine;
} Tile;
struct GameState
{
Tile tiles[NUM_TILES_X][NUM_TILES_Y];
};
typedef struct GameState GameState;
Im wondering how to properly call and set the structs? I have the following code where i would like to set state of each Tile.
void intialize_mines(){
for (int i =0; i < NUM_TILES_X; i++){
for (int j =0; j < NUM_TILES_Y; j++){
tiles[i,j].revealed = false;
}
}
}
But according to my console output i have done this incorrectly. How would i go about setting this correctly?

struct GameState just declares a type (just as int is just a type). You have to create a real struct in memory with GameState foo; similar to a normal variable (int foo;). And you can not access the contents of a struct without referencing the struct like foo.tiles. tiles on it's own is not known in this scope.
Afterwards you can access the struct with foo.tiles[i][j].revealed.
But to have access to this struct in your function you either have to pass it to the function as a pointer or declare the struct in filescope ( also called global). I would prefer the first version it is clearer an more function like.
Your function would look like this:
void intialize_mines( GameState *foo){
for (int i =0; i < NUM_TILES_X; i++){
for (int j =0; j < NUM_TILES_Y; j++){
foo->tiles[i][j].revealed = false; // -> is a special operator for pointers to structs. It's the same as (*foo).
}
}
}
the corresponding function call would be:
GameSate bar;
intialize_mines( GameState &bar);
You should also check how to use multidimensional arrays. You declared it correctly with two seperate [] but in your function you use [x,y] which is not correct in C. It would be the same as in the declaration tiles[i][j]

For a multi-dimensional array like tiles, you have to specify array subscript of each dimension within [] like this:
tiles[i][j].revealed = false;
This means that revealed belonging to jth column of ith row of tiles is set to false.
And you will have to define a structure variable of the type GameState before performing any operations on it.
GameState initGS;
void intialize_mines(){
for (int i =0; i < NUM_TILES_X; i++){
for (int j =0; j < NUM_TILES_Y; j++){
initGS.tiles[i][j].revealed = false;
}
}
}

You just missed to instantiate a GameState structure.
GameState gs;
void initialize_mines() {
for (int i =0; i < NUM_TILES_X; i++) {
for (int j =0; j < NUM_TILES_Y; j++) {
gs.tiles[i][j].revealed = false;
}
}
}

Related

How to use table pointer with fonction in C [duplicate]

This question already has answers here:
Passing 2D array of const size
(5 answers)
Closed 2 months ago.
This post was edited and submitted for review 2 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I have a struct like:
struct oda {
char isim[10];
int id[1];
};
and 2d table created with this type:
struct oda* tab[X][Y];
This table should be allocated dynamically on memory, so if we have product placement on x and y tab[X][Y] should point to our struct, otherway value of pointer tab[X][Y] = NULL
I have created a fonction for init this table:
void init_tab_empty(struct oda** ptr_tab)
{
int i, j;
for (i = 0; i < X; i++) {
for (j = 0; j < Y; j++) {
ptr_tablo[i][j] = NULL;
}
}
}
But this is not working, i have:
Cannot assign a value of type void * to an entity of type struct oda
Can you help me please?
I played with *'s but i can't understand what can i do more
it seems correct for me but not working
If I understood you well, you want to pass a table to your function. Then the following change will make it okay:
void init_tab_empty(struct oda ***tab)
{
int i, j;
for (i = 0; i < DIM_X; i++) {
for (j = 0; j < DIM_Y; j++) {
tab[i][j] = NULL;
}
}
}
This tells the function that you will input a table of pointers to struct oda data type.
There, you have:
struct oda *my_tab[DIM_X][DIM_Y];
...
init_tab_empty(my_tab);

I get error when trying to allocate 2D array, then use them

I am trying to allocate a 2D array in a function, but when I use this function my whole SDL apps crashes. If I comment out just the line where I call the function, there is no problem.
The return I get: Process returned -1073741819 (0xC0000005)
My Structs:
typedef struct Game
{
int x;
int y;
GameMode mode;
Field field;
} Game;
typedef struct Cell
{
CellType type;
bool shown;
bool marked;
} Cell;
This is how I initialize the Game and set a pointer of pointer for Cell.
Game game;
Cell **cells;
setup_ui(&game, cells);
setup_ui function: static int setup_ui(Game *game, Cell **cells)
In the setup_ui I have the function which causes the problem:
cells = setup_cells(game, cells);
And the function itself:
Cell** setup_cells(Game *game, Cell** cells){
cells = (Cell**) malloc(game->y*sizeof(Cell*));
for(int x=0; x<game->y; x++){
cells[x] = (Cell*) malloc(x * sizeof(Cell));
}
for(int i=0; i<game->x; i++){
for(int j=0; j<game->y; j++){
cells[i][j].type = simple;
cells[i][j].shown = false;
cells[i][j].marked = false;
}
}
return cells;
}
First of all, there's a mistake here:
for(int x=0; x<game->y; x++){
cells[x] = (Cell*) malloc(x * sizeof(Cell));
}
This should be malloc(game->x * sizeof(Cell)), since x is the current index, but game->x is the actual width. However, the error comes from the fact that here:
for(int i=0; i<game->x; i++){
for(int j=0; j<game->y; j++){
cells[i][j].type = simple;
cells[i][j].shown = false;
cells[i][j].marked = false;
}
}
i can go up to game->x, and j can go up to game->y, but the first dimension is of size game->y and the second dimension is of size game->x. So, you should flip the bounds of i and j.

I implemented a Map object in C, but using it gives me a Segmentation Fault

Below, I've defined a Map struct in C. It functions as a map, with setValue and getValue functions. Key values default to -1.
typedef struct {
int key;
int value;
} Index;
typedef Index Map[1000];
void initMap(Map *map)
{
for (int i = 0; i < 1000; i++)
{
Index thisIndex = *map[i];
thisIndex.key = -1;
thisIndex.value = 0;
}
}
int getValue(Map *map, int keyToGet)
{
for (int i = 0; i < 1000; i++)
{
Index thisIndex = *map[i];
if (thisIndex.key == keyToGet)
{
return thisIndex.value;
break;
}
}
return -1;
}
void setValue(Map *map, int keyToSet, int valueToSet)
{
int set = 0;
for (int i = 0; i < 1000; i++)
{
Index thisIndex = *map[i];
if (thisIndex.key == keyToSet)
{
thisIndex.value = valueToSet;
set = 1;
break;
}
}
if (set == 1)
return;
for (int i = 0; i < 1000; i++)
{
Index thisIndex = *map[i];
if (thisIndex.key == -1)
{
thisIndex.key = keyToSet;
thisIndex.value = valueToSet;
break;
}
}
}
int findValue(Map *map, int valueToGet)
{
for (int i = 0; i < 1000; i++)
{
Index thisIndex = *map[i];
if (thisIndex.value == valueToGet)
return thisIndex.key;
}
return -1;
}
At some point in the code, when run, I get a SegFault, presumably for accessing or trying to write over memory over which I do not have jurisdiction. My question is, where is that happening? Which function could be doing that, and where? I've sifted through multiple times and I can't seem to find where that would be happening.
There are two major errors in your code.
First, you typedef Map to an array. That means when you have a function prototype like this:
int getValue(Map *map, int keyToGet);
you really get something like this:
int getValue(Index (*map)[1000], int keyToGet);
In C, definition mimicks use, so you should access your map elements like this:
Index thisIndex = (*map)[i];
Your way to use it, *map[i] is equivalent to *(map[i]) and requires the array to be an array of 1,000 pointers to Index, which it isn't.
The (*map)[i]sytnax complicated, and you don't need it. Because your Map is an array, it decays into a pointer to its first element. You do not need to pass a pointer to an array if you want to modify the elements. It is enough to pass a pointer to the first element, which in your case can be either of:
int getValue(Map map, int keyToGet);
int getValue(Index map[], int keyToGet);
int getValue(Index *map, int keyToGet);
Accessing the elements of the array is then just map[i].
Fixing that fixes your segmentation fault, but it doesn't fix the fact that your map doesn't work. When you assign to a struct like this:
Index thisIndex = map[i];
and then modify thisIndex, you will not modify anything in your map! Here, thisIndex is a copy. When thisIndex goes out of scope, all modifications are lost.
You can either use the map directly:
if (map[i].key == keyToSet) {
map[i].value = valueToSet;
return;
}
(and why don't you? thisIndex is longer than map[i]), or you can make thisIndex a pointer to the array element:
Index *thisIndex = &map[i];
if (thisIndex->key == keyToSet) {
thisIndex->value = valueToSet;
return;
}
Here, you access and modify the fields of map[i] through the pointer.
Hiding an array in a typedef is probably not such a good idea. Perhaps at one time you want to keep the number of active items alongside the array. (That would make your code more efficient, because you wouldn't have to traverse all 1,000 items in the worst case.) In that case, you could make Map a struct with an array of 1000 key/value pairs and a count. Then you would have to pass pointers to the struct type, so that you can update the fields. This is left as an exercise ... :)

Creating a three dimensional struct array on the heap in c

I am trying to create a three dimensional struct array using malloc in c on MSVC. It compiles without error but when i debug it it gives an error after initializing some elements.
declaration:
typedef struct table_info
{
unsigned long size;
char code[33];
char path[300];
}table_info;
table is a global variable and is defined as:
struct table_info ***table=NULL;
malloc and initialize table:
char garb[33] = { '\0' };
char garb_path[300] = { '\0' };
table = (table_info***)malloc(ROWS* sizeof(**table));
for (int m = 0; m < ROWS; m++)
{
table[m] = (table_info**)malloc(COLS* sizeof(*table[m]));
for (int j = 0; j < COLS; ++j)
{
table[m][j] = (table_info*)malloc(DEPTH * sizeof(table[m][j]));
for (int k = 0; k < DEPTH; ++k)
{
table[m][j][k].size = 0;
strcpy_s(table[m][j][k].code, sizeof(table[m][j][k].code), garb);
memcpy(table[m][j][k].path, garb_path, sizeof(garb_path));
}
}
}
Am I initializing it correctly? or what should I correct to make it work?
The size passed to malloc is incorrect in the following line:
table[m][j] = (table_info*)malloc(DEPTH * sizeof(table[m][j]));
sizeof(table[m][j]) is just sizeof(**table), which is sizeof(table_info *). It should be sizeof(table_info), or alternatively sizeof(*table_info[m][j]) or sizeof(***table_info).
You also don't need to cast the result of malloc, which is generally frowned upon today (at least in C). See this post for more info.
So the following should work (in C):
table[m][j] = malloc(DEPTH * sizeof(*table[m][j]));

C: How to sort a Struct by one of its element? Can't use pointers

How do I sort struct like this one:
typedef struct
{
int weight;
int price;
Color color;
Equip equip;
}Cars;
by one of it's attributes like price, or weight? Automobil array is previously declared.
I can't use pointers, and any other built-in function.
Cars automobil[5];
Cars mobilOne={};
for(i=0; i<5; i++)
{
if((i+1)==5)
{
break;
}else
{
if (automobil[i].weight> automobil[i+1].weight)
{
mobilOne = automobil[i];
automobil[i] = automobil[i+1];
automobil[i+1] = mobilOne;
}
}
}
I tried to do this, this way, but it does not do anything...
Also if someone could tell me, how can I pass a struct like this one into a function I would be really thankful!
OK, well first what you are trying to do is not quite as bad as some people might tell you as for small N bubble sort is still pretty fast. The following will do you and of course you need a double loop:
int main() {
Cars automobil[NC];
// Initialiase automobil here
for (int i = 0; i < NC - 1; ++i) {
int am = i;
for (int j = i+1; j < NC; ++j) {
if ( automobil[am].weight > automobil[j].weight )
am = j;
}
if ( am != i) {
Cars tmp = automobil[am];
automobil[am] = automobil[i];
automobil[i] = tmp;
}
}
for (int i = 0; i < NC; ++i)
printf("%d\n", automobil[i].weight);
}
Notice that we can copy structs but even here we try to do it as little as possible.
However, it's very easy to say "I'll never have more than ten cars" and then find you are trying to sort several thousand so I would urge you to learn and understand qsort():
int carsSort(const void *a, const void *b) {
return ((Cars *) a)->weight - ((Cars *) b)->weight;
}
int main() {
Cars automobil[NC];
// Initialiase automobil here
qsort(automobil, NC, sizeof *automobil, carsSort);
for (int i = 0; i < NC; ++i)
printf("%d\n", automobil[i].weight);
}
John
PS: in reply to "how do I pass the array to a function?" remember one of the many wise sayings of K&R: "When an array name is passed to a function, what is passed is the location of the beginning of the array".
Hence:
int carsSort(const void *a, const void *b) {
return ((Cars *) a)->weight - ((Cars *) b)->weight;
}
void sortThem(Cars autom[]) {
qsort(autom, NC, sizeof *autom, carsSort);
}
int main() {
Cars automobil[NC];
// Initialiase automobil here
sortThem(automobil);
for (int i = 0; i < NC; ++i)
printf("%d\n", automobil[i].weight);
}
Inside sortThem() "autom" is a variable whose value is the address of automobil[0].
Without going into implementation details here is a procedural algorithm for a bubble sort (not in C): Bubble Sort Algorithm. Note, as mentioned in comments, this bubble sort implementation uses nested loops.
One other item to keep in mind: In order to switch two objects, a third temporary object of the same type needs to be used. For example:
int temp
int arr1[]={2,5,7,2,9,1,8,0,5,2,1};
int count = sizeof(arr1)/sizeof(arr1[0])
for(int i = 0; i < count-1; i++ )
{
if(arr1[i]>arr1[i+1])
{
temp = arr1[i];
arr1[i] = arr1[i+1];
arr[i+1] = temp;
}
}
Because you are sorting on a single member of a collection of members, the assignment swapping routine will need to swap every member each time the condition for a swap exists, i.e. although determining if the swap condition exists only considers one member, swapping will include all members: weight, price, Color and Equip. And, if Color and Equip are of struct type (your post does not specify), then each member of these objects belonging to array elements being compared, will also need to be swapped.
You should look forward to eventually using pointers as this will significantly reduce the number of assignment statements needed to complete this sort.

Resources