Initialize Array of Struct - C - c

If I have a variable called Tree * myTree, how could could I put this variable into an array of Tree*?
For example, I want to do something like:
Tree *allTrees[10];
allTrees = malloc(sizeof(Tree) * 10;
for (int i = 0; i < 10;i++)
{
allTrees[i] = malloc(sizeof(Tree));
}
allTrees[0] = myTree;
What am I doing wrong here?

You don't need to do
allTrees = malloc(sizeof(Tree) * 10);
because you are already allocating the array on the stack:
Tree *allTrees[10];
The rest should be fine.

Related

Allocate and assign to memory efficiently

I would like to create a new array of values, and I am not sure how to do this efficiently. Since to create the new array I have to call a function, passing the old array as a parameter. Right now my code looks something like:
float *newMeasurements1;
newMeasurements1 = malloc(sizeof(calcNewArray(oldArray)));
newMeasurements1 = calcNewArray(oldArray);
float *calcNewArray(float *oldArray) {
float *newArray;
int new_size = sizeof(oldArray) - outliers;
newArray = malloc((new_size) * sizeof(float));
for (i = 0; i < new_size; i++) {
newArray[i] = oldArray[i];
}
return newArray;
}
I am not sure if this is the correct way to do this because I have to call the function once to know the size of the new array. And then call the function a second time to actually assign the array to the allocated memory.
How best can I do this?
This line is useless:
newMeasurements1 = malloc(sizeof(calcNewArray(oldArray)));
just write this:
newMeasurements1 = calcNewArray(oldArray);
The malloc is already done in calcNewArray.
But there is another problem in calcNewArray, arrays decay to pointers to their first element when you pass them to a function, therefore sizeof(oldArray) is no the sizte bof the array you passed to calcNewArray but it is the size of a pointer. You need to pass the size of oldArray explicitely as a second parameter:
float *calcNewArray(float *oldArray, int oldsize) {
float *newArray;
int new_size = oldsize - outliers;
newArray = malloc((new_size) * sizeof(float));
for (i = 0; i < new_size; i++) {
newArray[i] = oldArray[i];
}
return newArray;
}

Append to the end of an array

My goal is to append a List to the end of an array. When i try to execute it give me segmentation fault.
I tried to make a little debug and the istruction that give me prolem is in the for cicle:
array[i] = tmp[i];
This is my code:
int i;
List *tmp = array;
array = (List *)malloc((dim+1) * sizeof(List));
for (i = 0; i < dim; i++) {
array[i] = tmp[i];
}
dim++;
array[dim-1] = (List)malloc(sizeof(struct TList));
memcpy(array[dim-1], set, sizeof(struct TList));
return array;
Where "dim" it's a global variable that i use to track the dimension of the array
I know that probably it's simple to do, but i really don't know how to solve this problem.
Thanks for help
First remark :
int i;
List *tmp = array;
array = (List*)malloc((dim+1) * sizeof(List));
for (i = 0;i < dim;i++){
array[i] = tmp[i];
}
Can be just that :
array = realloc(array, (dim+1) * sizeof(List));
in array[dim-1] = (List)malloc(sizeof(struct TList)); why the type in the cast is not also the type in the sizeof ?
But the true question is what do you expect doing that assignment except to loose memory through a memory leak ?
That line must be removed.
What are the definition of TList and list and the type of set ?
The line
memcpy(array[dim-1], set, sizeof(struct TList));
is wrong and must be (set must be a List)
array[dim-1] = set;
because array is vector of List, not a vector of List *

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 ... :)

Issue implementing dynamic array of structures

I am having an issue creating a dynamic array of structures. I have seen and tried to implement a few examples on here and other sites, the examples as well as how they allocate memory tend to differ, and I can't seem to get any of them to work for me. Any help would be greatly appreciated.
typedef struct node {
int index;
int xmin, xmax, ymin, ymax;
} partition;
partition* part1 = (partition *)malloc(sizeof(partition) * 50);
I can't even get this right. It gives me the following error:
error: initializer element is not constant
If anyone could explain how something like this should be implemented I would greatly appreciate it.
Also, once I have that part down, how would I add values into the elements of the structure? Would something like the below work?
part1[i]->index = x;
The compiler is complaining because you're doing:
partition* part1 = (partition *)malloc(sizeof(partition) * 50);
Do this instead:
partition* part1;
int
main(void)
{
part1 = (partition *)malloc(sizeof(partition) * 50);
...
}
Your version used an initializer on a global, which in C must be a constant value. By moving the malloc into a function, you are "initializing the value" with your code, but you aren't using an initializer as defined in the language.
Likewise, you could have had a global that was initialized:
int twenty_two = 22;
Here 22 is a constant and thus allowable.
UPDATE: Here's a somewhat lengthy example that will show most of the possible ways:
#define PARTMAX 50
partition static_partlist[PARTMAX];
partition *dynamic_partlist;
int grown_partmax;
partition *grown_partlist;
void
iterate_byindex_static_length(partition *partlist)
{
int idx;
for (idx = 0; idx < PARTMAX; ++idx)
do_something(&partlist[idx]);
}
void
iterate_byptr_static_length(partition *partlist)
{
partition *cur;
partition *end;
// these are all equivalent:
// end = partlist + PARTMAX;
// end = &partlist[PARTMAX];
end = partlist + PARTMAX;
for (cur = partlist; cur < end; ++cur)
do_something(cur);
}
void
iterate_byindex_dynamic_length(partition *partlist,int partmax)
{
int idx;
for (idx = 0; idx < partmax; ++idx)
do_something(&partlist[idx]);
}
void
iterate_byptr_dynamic_length(partition *partlist,int partmax)
{
partition *cur;
partition *end;
// these are all equivalent:
// end = partlist + partmax;
// end = &partlist[partmax];
end = partlist + partmax;
for (cur = partlist; cur < end; ++cur)
do_something(cur);
}
int
main(void)
{
partition *part;
dynamic_partlist = malloc(sizeof(partition) * PARTMAX);
// these are all the same
iterate_byindex_static_length(dynamic_partlist);
iterate_byindex_static_length(dynamic_partlist + 0);
iterate_byindex_static_length(&dynamic_partlist[0]);
// as are these
iterate_byptr_static_length(static_partlist);
iterate_byptr_static_length(static_partlist + 0);
iterate_byptr_static_length(&static_partlist[0]);
// still the same ...
iterate_byindex_dynamic_length(dynamic_partlist,PARTMAX);
iterate_byindex_dynamic_length(dynamic_partlist + 0,PARTMAX);
iterate_byindex_dynamic_length(&dynamic_partlist[0],PARTMAX);
// yet again the same ...
iterate_byptr_dynamic_length(static_partlist,PARTMAX);
iterate_byptr_dynamic_length(static_partlist + 0,PARTMAX);
iterate_byptr_dynamic_length(&static_partlist[0],PARTMAX);
// let's grow an array dynamically and fill it ...
for (idx = 0; idx < 10; ++idx) {
// grow the list -- Note that realloc is smart enough to handle
// the fact that grown_partlist is NULL on the first time through
++grown_partmax;
grown_partlist = realloc(grown_partlist,
grown_partmax * sizeof(partition));
part = &grown_partlist[grown_partmax - 1];
// fill in part with whatever data ...
}
// once again, still the same
iterate_byindex_dynamic_length(grown_partlist,grown_partmax);
iterate_byindex_dynamic_length(grown_partlist + 0,grown_partmax);
iterate_byindex_dynamic_length(&grown_partlist[0],grown_partmax);
// sheesh, do things ever change? :-)
iterate_byptr_dynamic_length(grown_partlist,grown_partmax);
iterate_byptr_dynamic_length(grown_partlist + 0,grown_partmax);
iterate_byptr_dynamic_length(&grown_partlist[0],grown_partmax);
}
There are two basic ways to interate through an array: by index and by pointer. It does not matter how the array was defined (e.g. global/static --> int myary[37]; or via malloc/realloc --> int *myptr = malloc(sizeof(int) * 37);). The "by index" syntax and "by pointer" syntaxes are interchangeable. If you wanted the 12th element, the following are all equivalent:
myary[12]
*(myary + 12)
*(&myary[12])
myptr[12]
*(myptr + 12)
*(&myptr[12])
That's why all of the above will produce the same results.

Value changes in a struct when editing another struct in another function

I've run into a problem with structs which I believe is caused by incorrect mallocs, or possibly rather my reallocs. I've cut down the code as much as possible to only show what I believe could be relevant, so nearly all the actual operations are omitted.
The struct I have looks as follows:
struct poly_t {
int nvars, *factor, *exp;
};
The value that's acting weird is nvars, which to me would signify that I'm somehow not reserving memory properly. What I do is that I first have a function that creates and fills the struct, then I have another function where I send two of these structs in and create a third identical struct. When editing the value of nvars in this third struct, it very rarely also edits the value of nvars in the first struct. When running gdb, it shows the exact row it happens on is when I do thirdp->nvars++; in my mul function.
So with this function I create my first and second structs (a and b).
poly_t* new_poly_from_string(const char* a){
struct poly_t* p = malloc(sizeof(struct poly_t));
p->nvars = 0;
p->factor = malloc(strlen(a) * sizeof(int));
p->exp = malloc(strlen(a) * sizeof(int));
for (int i = 0; i < strlen(a); i++){
//do stuff to put a into p, using at most p->factor[p->nvars] and the same for p->exp
p->factor = realloc(p->factor, p->nvars*sizeof(int));
p->exp = realloc(p->exp, p->nvars*sizeof(int));
printf("%d", p->nvars); //At this point, nvars is the correct value
return p;
}
And below is the function that works in 9/10 cases but in some rare cases it doesn't. I've marked the exact row that changes a->nvars with an arrow -->.
poly_t* mul(poly_t* a, poly_t* b){
struct poly_t* thirdp = malloc(sizeof(struct poly_t));
thirdp->nvars = 0;
thirdp->factor = malloc((a->nvars + b->nvars) * sizeof(int));
thirdp->exp = malloc((a->nvars + b->nvars) * sizeof(int));
for (int i = 0; i < a->nvars; i++){
for (int j = 0; j < b->nvars; j++){
for (int k = 0; k < p->nvars; k++){
if (p->exp[k] == a->exp[i] + b->exp[j]){
p->factor[k] += a->factor[i]*b->factor[j];
found = 1;
break;
}
}
if (!found){
p->factor[p->nvars] = a->factor[i]*b->factor[j];
p->exp[p->nvars] = a->exp[i] + b->exp[j];
--> p->nvars++; //This is the row that changes a->nvars according to gdb
}
}
}
return thirdp;
}
Here's what I got when running gdb while trying to figure out what was changing a->nvars. Note that p is the same as thirdp above, I just renamed it here for clarity.
edit: Readded the actual code in the mul function
You are allocating space for the sum of the number of integers
a->nvars + b->nvars
I wonder what you do in
//fill thirdp->factor and thirdp->exp
As you have nested for loops I suspect you may be generating
a->nvars * b->nvars //multiply
items and hence running off the end of allocated space. You now show us the code and we see
if (!found){
// --- here ----
p->factor[p->nvars] = a->factor[i]*b->factor[j];
p->exp[p->nvars] = a->exp[i] + b->exp[j];
p->nvars++;
}
At the point I mark here you should check the value of p->nvars, I think it has the possibility to reach a value greater than (a->nvars + b->nvars).
I think to be safe allocate the space for (a->nvars * b->nvars) ints.
The problem was as I believed in the mallocs. Specifically the following two rows:
thirdp->factor = malloc((a->nvars + b->nvars) * sizeof(int));
thirdp->exp = malloc((a->nvars + b->nvars) * sizeof(int));
I simply wasn't allocating enough memory which caused the weird behaviour. What I wanted was:
thirdp->factor = malloc((a->exp[0] + b->exp[0]) * sizeof(int));
thirdp->exp = malloc((a->exp[0] + b->exp[0]) * sizeof(int));
Unfortunately since I didn't give any of the indata, or really much context, you guys probably couldn't have figured that out <.< Sorry!

Resources