Can't store a struct containing a pointer - c

I have three structs :
struct Map
{
int width, height;
int* cases;
};
typedef struct Map Map;
struct Ship
{
int x, y, length, firstShoot, color, hasBeenDiscovered;
};
typedef struct Ship Ship;
struct Player
{
int activeShips;
Map map[2];
char lastMoves[5][128];
Ship ships[10];
int shipcolor[4];
int color;
};
typedef struct Player Player;
I use the map structure as a 2d dynamic array. Here are my functions to manipulate the map :
void mallocMap(Map* map, int width, int height)
{
map->cases = malloc(sizeof(int) * width * height);
map->width = width;
map->height = height;
if (map->cases == NULL)
{
printf("Erreur d'allocation de memoire\n");
exit(0);
}
}
void freeMap(Map* map)
{
free(map->cases);
}
int getMapValue(Map map, int x, int y)
{
return *(map.cases + y*map.width + x);
}
void setMapValue(Map* map, int value, int x, int y)
{
*(map->cases + y*map->width + x) = value;
}
Now what I'm doing is I'm creating a variable player of type Player, asks the user the width and height of the map and allocate memory for the map (malloc(sizeof(int)*width*height)).
Next what I want to do is to be able to store the struct Player in a file and the values of the cases but I don't know how I could do it.
Any suggestion ?

You're not reading the values back in properly:
fseek(file, sizeof(Player), SEEK_SET); // set the cursor after the struct
fread(&player->games, sizeof(int), 1, file); // read the value
fseek(file, sizeof(int), SEEK_CUR); // set the cursor after the first value
fread(&player->map.cases, sizeof(int), 1, file); // read the value
In the first read, you pass in &player->games as the address to write to. This expression has type int **. Rather than writing into the memory you allocated, you're writing into the pointer that contains that address. The same problem exists in the other read.
Remove the address-of operator from each of the fread calls. Also, the calls to fseek are redundant since the file pointer is already at the correct place, so you can remove them.
fread(player->games, sizeof(int), 1, file); // read the value
fread(player->map.cases, sizeof(int), 1, file); // read the value

Related

About struct and arrays (C language)

I'm trying to create code using a struct and a pointer, for example:
struct Vector()
{ double x,y,z;};
struct vector *p[][][]. I need a 3d parameter which have x,y and z coordinates for a molecular simulation.
The problem is: I want to run in Ubuntu's terminal and give the values of sample size using argc argv on terminal.
So I ask you guys: Can I create a struct array? I believe this will solve my problem.
You could take a different approach instead of using command line arguments, as suggested in the previous answer.
You can take user input using file input indirection to stdin, which can be a convenient way of processing data. Your command line call looks like:
./your_prog < data
Where data is a data file with a set of three space separated values on each line:
1 1 1
2.1 2.2 2.3
3.1 3.2 3.3
You could then process the data using something like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct vector {
double x;
double y;
double z;
} Vector;
Vector *createVector(double x, double y, double z);
int main()
{
// Initialize an array of pointers to Vector
Vector **array = calloc(5, sizeof(*array));
double x = 0, y = 0, z = 0;
size_t lineCount = 0;
while(1) {
// Take input from stdin
ssize_t r = scanf("%lf%lf%lf", &x, &y, &z);
if (r == EOF) {
// No more data so finish
break;
}
// Note that you need to check the size of the array
// and resize using realloc() as necessary within this loop.
// The array needs to have space for at least lineCount + 1 elements.
// Check this and reallocate before trying to add a
// new element to the array.
array[lineCount] = createVector(x, y, z);
lineCount++;
}
for (size_t i = 0; i < lineCount; i++) {
// Do something with each element of the array
printf("Vector %zu: (%lf, %lf, %lf)\n", i, array[i]->x, array[i]->y, array[i]->z);
}
// You have dynamically allocated memory, so it should be freed.
for (size_t i = 0; i < lineCount; i++) {
free(array[i]);
}
free(array);
return 0;
}
// Create a pointer to a Vector, dynamically allocating memory and returning
// a pointer to the new array.
Vector *createVector(double x, double y, double z)
{
Vector *v = calloc(1, sizeof(*v));
v->x = x;
v->y = y;
v->z = z;
return v;
}
Hope this helps.
I've just solved the problem.
typedef struct
{
double x,y,z;
}vetor;
vetor ***p;
void alloc(int lx, int lz)
{ int i,j=0;
int ly=lx;
p=calloc(lx,sizeof(vetor**));
for(i=0;i<lx;i++)
{
p[i]=calloc(lx,sizeof(vetor*));
for (j=0;j<lx;j++)
{
p[i][j]=calloc(lz,sizeof(vetor));
}
}
}
I was using sizeof(double*) but the member p is a vetor struct type.
So with this i can make a member p[a][b][c] dynamically using pointers and let it a global member ( in my code i have to) and put the values a,b and c on terminal.
I would like to thank you for the answers which makes me think a lot about this problem. Thank you for attention too.
Note that the struct definition you provided ( struct Vector() ) as an example is not a struct definition.
But yes, you can use int argc, char *argv[] to read the command line for user input.
Then you can use something as simple as
If(argc != 2) {
printf("usage error, exiting");
return 0;
}
int array_size = atoi(argc[1]);
Then for example you can easily create an array of struct by declaring a typedef:
typedef struct {
double x;
double y;
double z
} MOLECULE;
MOLECULE molArray[array_size];//from user input - each of array_size instances contains x,y,z members.
There are several ways to instantiate a pointer reference to this example struct, i.e.
MOLECULE *pMolecule = malloc(array_size)*sizeof(*molecule));
Or
MOLECULE *pMolecule = {0};
MOLECULE molecule = {1.0,2.0,3.0};//simple sample of data
pMolecule = &modlecule;//pointer pointing to area in memory containing instance of MOLECULE
Note that with an array of struct, it becomes impracticable to use user input to populate the many members, reading that information from a file, or a database is probably best.
If you provide more details, this answer can do the same. Just flag me in a comment
EDIT To address question in comments "...but how it would if I needed a MOLECULE molArray[x][y][z] ? and x,y,z is a dynamic value which I enter in the beginning of the program?":
Using VLA allows a way to dynamically defined sizes of objects when the sizes needed are not known until run-time. example...
defined MOLECULE struct differently since you want 3D array of struct, no need to define members x, y, z. You need to decide what members will define your actual struct. Because I do not know, I can only guess at what characteristics you want to include in this struct illustration:
typedef struct {
char R;
char G;
char B;
}COLOR;
typedef struct {
double mass;
COLOR color;
double size;
char molec_formula[80];
}CHARAC;
typedef struct {
char name[80];
CHARAC charac;
}MOLECULE;
int main(int argc, char *argv[])
{
if(argc != 4) // prog.exe <x> <y> <z>
{
printf("usage error, exiting");
return 0;
}
int x = atoi(argv[1]);//could also use strtol() here as well
int y = atoi(argv[2]);
int z = atoi(argv[3]);
// from MOLECULE definition above:
MOLECULE molArray[x][y][z];//now you have an 3D array of a struct using VLA
...(more code)
So, if your program name was prog.exe, and you wanted a 3D array with dimensions: 10, 12, 13. then typing this on command line:
prog 10 12 13
Will result in creating molArray[10][12][13]

C saving game state, reducing passed variables

I've been wondering if there's a way to do a function that saves game state but in transparent way. It's not a question about actual saving (I know how to save to file etc), it's about writing it in a clear, simple and understandable way.
So far I've came to three ideas (remember, I wish it could be a function or some easy thing like savegame()), none is perfect:
Put every variable I want to save into a struct like:
struct state{
int hp;
pos position;
int x;
int y;
...
};
...
if(savegame==1) {
state game;
game.hp=hp;
game.position=position;
game.x=x;
game.y=y;
...
savegame(game);
}
as you can see, it's not looking any good, it takes so many lines to do just a saving: what if I would like to save like 40 variables? What if I want to do saving in like 5-6 places in a code?
Make my function long as snake (this gives a problem with loading it back, so for example I also put a loadgame func):
void savegame(int hp, pos position, int x, int y,...) // too long
{ ... }
void loadgame(int &hp, pos &position, int &x, int &y,...) // too long
{ ... }
...
int main()
{
...
savegame(hp, pos, x, y, ...) // too long
...
loadgame(hp, pos, x, y, ...) // too long
}
again, if it would have 40 variables inside(and i also would like to call savegame or loadgame like 5-6 times), it would take like 4 lines of code each(i just skip an idea to put it in 1 line)
Start my program with struct containing game state, and make all calculations, actually all game on that struct
struct gamestate{
int hp;
pos position;
int x;
int y;
}
...
int main()
{
struct gamestate s;
s.x++;
...
}
but this leads to a problem where everytime I make calculations I have to add this 's' at beggining.
Conclusion:
My idea was to maybe change second option just to reduce every call of savegame(...); to simple savegame();, is there a way to do it? Without define?
Here is a dynamic way to do something similar to what you describe in your 1st option, i.e. track a game state using pointer to struct but that also stores and recovers that data to and from a binary file...
The following .c and .h files illustrate the idea that you can use a compound struct, i.e. one containing several other structs, that at any one time contain all of the values representing states in your program. This is very easily passed via a function(s) with very few arguments (prototyped eg. as char *GetState(state *in, const char *filespec); and char *SetState(state *out, const char *filespec); ) which in turn would write or read the contents of the struct into/out of a binary buffer. I have used this method to store and retrieve multiple sets of state data within files.
Note, the structs have random fields that of course you will modify as needed, but the idea is that you can pass a single pointer value that points to all the state data, in every function where state date is updated, or needs to be stored.
so_SaveGameState.c
#include <so_SaveGameState.h>
unsigned char *pByteA;
GAME_STATE game = {{{"jim", "C:\\ico1.ico", {10, 120, 3}}, {"joe", "C:\\ico2.ico", {80, 10, -5}},{"larry", "C:\\ico3.ico", {15, -45, -45}},{"sue", "C:\\ico4.ico", {-100, -45, 45}}}, ENVR_3};
GAME_STATE *pGame = NULL;
int main(void)
{
pGame = &game;//point to populated memory
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
//example function that changes game state
UpdatePlayerPosition(&pGame, 2);
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
UpdatePlayerPosition(&pGame, 2);
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
UpdatePlayerPosition(&pGame, 2);
printf("Player 3 position\nx = %d\ny = %d\nz = %d\n", game.plyr[2].pos.x, game.plyr[2].pos.y, game.plyr[2].pos.z);
//prepare an instance of game state for storeing
(const GAME_STATE *)pByteA = &game;
int len1 = sizeof(game);
BOOL status = storeState("C:\\tempextract\\binFileStruct.bin", pByteA, len1);
//recover a stored state
unsigned char *buf = recoverState("C:\\tempextract\\binFileStruct.bin");
GAME_STATE *game_2 = (GAME_STATE *)buf;
free(game_2);
return 0;
}
unsigned char * recoverState(const char *filespec)
{
size_t sz = 0;
int n = 0;
unsigned char *binBuf = NULL;
FILE *fp = fopen(filespec, "rb");
if(fp)
{
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
fseek(fp, 0L, SEEK_SET);
rewind(fp);
binBuf = calloc(sz, sizeof(*binBuf));
n = fread(binBuf, sizeof(unsigned char), sz, fp);
fclose(fp);
}
if(n == sz)
{
return binBuf;
}
else
{
return NULL;
}
}
int storeState(const char *filespec, const unsigned char *buf, size_t sz)
{
int count = 0;
FILE *fp = fopen(filespec, "wb");
if(fp)
{
count = fwrite(buf, sizeof(unsigned char), sz, fp);
fclose(fp);
}
return (count == sz) ? 1 : 0;
}
void UpdatePlayerPosition(GAME_STATE **game, int player)
{
static int x=0, y=0, z=0;
static BOOL toggle = TRUE;
toggle = (toggle == 1) ? -1 : 1;
srand(clock());
//using fake assignment here
//i.e. you would have other criteria to set actual position
x += toggle * rand()%300;
y += toggle * rand()%300;
z += toggle * rand()%300;
(*game)->plyr[player].pos.x = x;
(*game)->plyr[player].pos.y = y;
(*game)->plyr[player].pos.y = z;
}
so_StoreGameState.h
typedef enum {//environment
ENVR_1, //bad weather
ENVR_2, //hill
ENVR_3, //pit
ENVR_4, //angry birds
ENVR_5, //enemy guard
MAX_OBST
}ENVR_TYPE;
typedef struct {
int x;
int y;
int z;
}POS;
typedef struct {
ENVR_TYPE envir;
//...
}ENVIR;
typedef struct {
char name[20];
char iconFile[260];
POS pos;
//...
}PLAYER;
typedef struct {
PLAYER plyr[4];
ENVIR env;
//...
}GAME_STATE;
extern GAME_STATE game;
unsigned char * recoverState(const char *filespec);
int storeState(const char *filespec, const unsigned char *buf, size_t sz);

How can I pass integers read from Text file into struct function?

I want to pass a txt file of integers into the smallest_xcoord struct. I am trying to get the convex hull. My issue is, I keep getting an error when trying. How can i pass integers read from text file into my struct function? I have not included my struct Point but that stores an int x; and int y; (for the convex hull points).
```
//GLOBAL Variable
static int integers[100000];
int load_integers(const char* filename)
{
//int integers[100000];
FILE *fp = NULL;
int value;
int i = -1;
if ((fp= fopen (filename, "r"))==NULL)
{
return -1;
}
while (fscanf (fp, "%u", &value)&& !feof(fp) && ++i <100000)
{
integers[i] = value;
}
fclose(fp);
return i+1;
}
struct Point smallest_xCoord (struct Point points, int numPoints)
{
struct Point points[];
struct Point minX_point = points[0];
int i;
for(i=1;i<numPoints;i++)
{
if ((points[i].x) < (minX_point.x))
{
minX_point = points[i];
}
else if (points[i].x == minX_point.x)
{
if (points[i].y < minX_point.y)
{
minX_point=points[i];
}
}
}
return minX_point;
}
int main(int argc, char *argv[])
{
int num_ints=0;
if (argc <2)
{
fprintf(stderr, "%s <file>\n",argv[0]);
return -1;
}
if ((num_ints = load_integers(argv[1])) <=0)
{
fprintf(stderr, "Error reading from file: %s\n",argv[1]);
return -1;
}
smallest_xCoord(integers, num_ints);
return 0;
}
```
smallest_xCoord(integers, num_ints);
First, you can't pass an integer data type to a "Point" data type parameter.
Second, you can't pass an array integer data type to a single Point parameter.
struct Point smallest_xCoord (struct Point points, int numPoints)
{
struct Point points[];
Third, you can't create a new variable inside of x_Coord with similar name to its parameter because you're re-declaring it.
If you want to pass in an array as a paramater, you gotta use a pointer (*) before its name. For the smallest_xCoord function to work, you need to specify which member of the Point struct you want to compare or assign it to. My suggestion to you is, you probably need to change that global int array variable to a global Point array variable and load it with value from your file which I assume, should contain values for x and y coordinates so that you can compare the loaded global Point array to the one you're providing. Then, change the parameter of smallest_xCoord to "struct Point *points" or "struct Point points[]" since you are passing an array to be compared.

Casting void* to a variable data type in C

I try to write a function, that finds void pointers in a data structure. The function has to cast the void* to any kind of struct.
Let's say I write a struct, which I store in my data sturcture in form of a void pointer. Then I calls the function, which prints information of all stored data elements.
To do that the function has to know to which type it should cast.
So my question is: Is it possible to give the function the informations it needs in form of a parameter somehow?
example code:
typedef struct{
int a, b
} teststruct;
void DSOut(datastructure* ds, datatypeinfo dt){
//...
//search for data in ds
//...
//if data is found cast it to the type defined in dt
//and print out the a and b fields
}
int main(){
datastructure* ds = DSCreate(4, 3); //can hold any type of data,
//but should hold just one at a time
//4 and 3 are just example parameters
teststruct ts;
ts.a = 4;
ts.b = 10;
teststruct ts2;
ts2.a = 6;
ts2.b = 12;
//Add the teststructs to the data-structure
DSAdd(2, 2, ts); //the numbers are just for example
DSAdd(4, 1, ts2);
datatypeinfo dt = teststruct; //stores the type teststruct for DSOut
DSOut(ds, dt); //function, that prints information of all added teststructs
return 0;
}
in this example DSOut(x,y) should print the following:
- on position 2, 2 is an element which holds following data: 4, 10.
- on position 4, 1 is an element which holds following data: 6, 12.
Do you think this is possible ?
Types cannot be passed as parameters in C, so the short answer to your question is "no, it cannot be done", at least not in the general case. You could pass something that would allow you to identify one of a limited set of types, and then hard-code how to handle each of those types (I'm thinking of a big switch statement). Since you don't specify what datatypeinfo looks like, it isn't clear how general you expect it to be.
I can think of adding a type identifier field to your struct and check it's value to decide how to print it, and initialize the structs with functions to take care of the type field
enum Types {
Point3D,
Point2D
};
struct Base {
enum Types type;
};
struct Point3D {
enum Types type;
int x;
int y;
int z;
};
struct Point2D {
enum Types type;
int u;
int v;
};
void print(void *data)
{
switch (((struct Base *)data)->type)
{
case Point2D:
{
struct Point2D *point;
point = (struct Point2D *)data;
printf("2D: %d, %d\n", point->u, point->v);
}
break;
case Point3D:
{
struct Point3D *point;
point = (struct Point3D *)data;
printf("3D: %d, %d, %d\n", point->x, point->y, point->z);
}
break;
}
}
void initialized2dPoint(struct Point2D *const point, int u, int v)
{
if (point == NULL)
return;
point->type = Point2D;
point->u = u;
point->v = v;
}
void initialized3dPoint(struct Point3D *const point, int x, int y, int z)
{
if (point == NULL)
return;
point->type = Point3D;
point->x = x;
point->y = y;
point->z = z;
}
int main(void)
{
struct Point2D point2d;
struct Point3D point3d;
initialized2dPoint(&point2d, 1, 2);
initialized3dPoint(&point3d, 3, 4, 5);
print(&point2d);
print(&point3d);
return 0;
}

trouble with fread() function in the code

I wrote a program in C to open bitmap image and save the dimension the image. i am having some problem to write the fread() function. please tell me what should be the correct format for the function in the code that i have written.
here i have used pointer array because i have to open multiple bitmap images.
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
void fskip(FILE *fp, int num_bytes)
{
int i;
for (i=0; i<num_bytes; i++)
fgetc(fp);
}
typedef struct tagBITMAP /* The structure for a bitmap. */
{
int width;
int height;
//unsigned char *data;
} BITMAP;
int main()
{
int temp1=0;
BITMAP *bmp[50];
FILE *fp = fopen("splash.bmp","rb");
if (fp!=NULL && (fgetc(fp)=='B' && fgetc(fp)=='M')){
bmp[temp1] = (BITMAP *) malloc (sizeof(BITMAP));
fskip(fp,16);
fread(&bmp[temp1].width, sizeof(int), 1, fp);
fskip(fp,2);
fread(&bmp[temp1].height,sizeof(int), 1, fp);
fclose(fp);
}
else exit(0);
getch();
}
fread(&bmp[temp1].width, sizeof(int), 1, fp);
should be:
fread(&(bmp[temp1]->width), sizeof(int), 1, fp);
because bmp[temp1] is address of struct use -> operator instead of . Same error is in second fread().
. DOT that works with value variable called element selection by reference.
-> is used called element selection through pointer.

Resources