Reputation: 99
I am creating a Center of Mass program and i'm trying to generalize it, it only works for 3D at most. Using structures with elements for the 3Ds and mass. The number of variables of type objects, i would like to be defined by the user and not me. But I can't find a way to create the variables using a loop. Maybe there's a different way to do it and I just don't know about it. Here's an example of my code, it's not the entire code, but it's the same logic for all the equations.
#include <stdio.h>
#include <stdlib.h>
struct objects
{
int Xcdnt;
int Ycdnt;
int Zcdnt;
int Mass;
};
int main()
{
int objectcount = 0;
int dimensioncount = 0;
printf("How many objects are there?");
scanf(" %d", &objectcount);
printf("How many dimensions are used?");
scanf(" %d", &dimensioncount);
for(int i = 0; i < objectcount; i++)
{
struct objects (i);
}
for(int i = 0; i < objectcount; i++)
{
printf("X coordinate is %d.\n", (i).Xcdnt);
}
return 0;
}
Upvotes: 2
Views: 9379
Reputation: 84599
This is a fundamental part of handling memory in C. It's not difficult, but one of the things you have to make friends with before the light-bulb winks on. (note: if your compiler supports the C99 Variable Length Array objects, you can use a VLA instead of dynamically allocating, that is not addressed here)
You have three tools to allocate memory dynamically, malloc
, calloc
and realloc
. (calloc
does the same thing as malloc
, but initializes all bytes to zero -- useful when you want to insure all memory is initialized and only slightly slower than malloc
)
For your example, you could allocate memory dynamically for your objects as follows (note the additional information in the /* comments */
below):
#include <stdio.h>
#include <stdlib.h>
typedef struct { /* a typedef will do (and make things easier) */
int xcdnt; /* C generally uses all lowercase variable and */
int ycdnt; /* function names, avoiding MixedCase or */
int zcdnt; /* camelCase, reserving all uppercase for */
int mass; /* constants and macros. */
} object;
int main (void) {
int objectcount = 0;
int dimensioncount = 0;
object *objects = NULL;
printf ("How many objects are there?: ");
if (scanf (" %d", &objectcount) != 1) { /* validate ALL user input */
fprintf (stderr, "error: invalid conversion or EOF.\n");
return 1;
}
printf ("How many dimensions are used?: ");
if (scanf (" %d", &dimensioncount) != 1) {
fprintf (stderr, "error: invalid conversion or EOF.\n");
return 1;
}
/* create objectcount objects using calloc */
objects = calloc (objectcount, sizeof *objects);
if (!objects) { /* validate all memory allocations */
fprintf (stderr, "error: virtual memory exhausted.\n");
return 1;
}
/* create some random values */
for (int i = 0; i < objectcount; i++) {
objects[i].xcdnt = i;
objects[i].ycdnt = i + 1;
objects[i].zcdnt = i + 2;
objects[i].mass = i % 10 + 5;
}
printf ("\ndimensioncount: %d\n\n", dimensioncount);
/* output the random data in objects */
for (int i = 0; i < objectcount; i++) {
printf ("X coordinate is %d.\nY coordinate is %d.\n"
"Z coordinate is %d.\nmass is: %d\n\n",
objects[i].xcdnt, objects[i].ycdnt, objects[i].zcdnt,
objects[i].mass);
}
free (objects); /* don't forget to free the memory you allocate */
return 0;
}
Example Use/Output
$ /bin/dynamicobjects
How many objects are there?: 10
How many dimensions are used?: 3
dimensioncount: 3
X coordinate is 0.
Y coordinate is 1.
Z coordinate is 2.
mass is: 5
X coordinate is 1.
Y coordinate is 2.
Z coordinate is 3.
mass is: 6
<snip... objects[2-7]>
X coordinate is 8.
Y coordinate is 9.
Z coordinate is 10.
mass is: 13
X coordinate is 9.
Y coordinate is 10.
Z coordinate is 11.
mass is: 14
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to write beyond/outside the bounds of your allocated block of memory, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind
is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/dynamicobjects
==9105== Memcheck, a memory error detector
==9105== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9105== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9105== Command: ./bin/dynamicobjects
==9105==
How many objects are there?: 10
How many dimensions are used?: 3
dimensioncount: 3
X coordinate is 0.
Y coordinate is 1.
Z coordinate is 2.
mass is: 5
<snip... remaining>
==9105==
==9105== HEAP SUMMARY:
==9105== in use at exit: 0 bytes in 0 blocks
==9105== total heap usage: 1 allocs, 1 frees, 160 bytes allocated
==9105==
==9105== All heap blocks were freed -- no leaks are possible
==9105==
==9105== For counts of detected and suppressed errors, rerun with: -v
==9105== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have any further questions.
Upvotes: 1
Reputation: 580
Use malloc to create an array dynamically
struct objects* objs = malloc(sizeof *objs * objectcount);
You could also create a local array like this:
struct objects objs[objectcount];
but you risk blowing up the stack if it's too big.
Upvotes: 0
Reputation: 141638
To create an array of objects you would write, instead of your loop,
struct objects foo[objectcount];
where foo
is the name of the array, and objectcount
is how many items are in the array.
Then the code to access each element would be:
for(int i = 0; i < objectcount; i++)
{
printf("X coordinate is %d.\n", foo[i].Xcdnt);
}
although you need to have some other steps before that to actually assign a value to foo[i].Xcdnt
before printing it out.
Upvotes: 0
Reputation: 50210
you need to malloc an array of object. Your current code just looops creating and destroying the same one
struct objects* objects = malloc(objectcount * sizeof(struct objects));
for(int i = 0; i < objectcount; i++)
{
objects[i].Xcdnt = 42;
.....
}
Upvotes: 1