Adding a struct to an array - c

Given a struct Element:
typedef struct {
char someString[9]
int value;
} Element
and an array elementList:
Element elementList[5];
is there an easy way to dynamically add an Element to each index of the list? I have tried creating a function add_element that takes in the list and modifies it there but I'd prefer something equivalent to Java's elementList[i] = new Element.

There's no need, that array consists of structure instances.
You can do e.g.:
strcpy(elementList[0].someString, "foo");
elementList[0].value = 4711;
This is not possible in Java, where everything is a reference, but in C you can do this. If you want a bunch of NULL-able references, in C you use pointers:
Element *elementList[5]; /* An array of 5 pointers to type Element. */
Then you have to use e.g. heap allocations to make sure there is memory before accessing the Element:
elementList[0] = malloc(sizeof *elementList[0]); /* This might fail! */
elementList[0]->value = 17;

As declared, you've created a 5-element array of Element instances; there's no need to allocate new Element objects. You can go ahead and read/assign each member of each element:
element[i].value = some_value();
strcpy( element[i].someString, some_string() );
If you want to emulate the Java method, you'd do something like the following:
Element *elementList[5]; // create elementList as an array of *pointers* to Element
...
elementList[i] = malloc( sizeof *elementList[i] ); // dynamically allocate each element
Note that in this case, you'd use the -> operator instead of the . operator to access each Element member, since each elementList[i] is a pointer to Element, not an Element instance:
elementList[i]->value = some_value();
strcpy( elementList[i]->someString, some_string() );
In either case, the array size is fixed; you cannot grow or shrink the number of elements in the array.

Related

how do i delete arrays of typedef structs?

I am trying to delete an array of initialized structs e.g. reset the array
My struct:
struct entry{
char name[NAME_SIZE];
int mark;
};
typedef struct entry Acct;
Acct dism2A03[MAX_ENTRY];
Acct clear[0]; << temp struct to set original struct to null
My attempt:
entry_total keeps track of how many structs in the struct array dism2A03[x] have values set in them.
I tried to create an empty array of the same struct clear[0]. Looped through initialized arrays in dism2A03[x] and set them to clear[0]
for(m=0;m<entry_total;m++){
dism2A03[m]=clear[0];
}
break;
However, it is setting them to 0, i want them to become uninitialized e.g. no values in them
You cannot have memory with no value in it. It's physically impossible. It's due to the laws of physics of our universe :-)
Also, this:
Acct clear[0];
is wrong. You cannot have an array with zero elements. Some compilers will allow this as an extension, but it's not valid C. And for the compilers that allow this, it doesn't do what you think it does.
It would seem to me that what you want instead is to resize the array. To do that, you would need to copy the elements you want to keep into a new array, and then free() the old one. To do that, you need to create dism2A03 using dynamic memory:
Acct *dism2A03 = malloc(sizeof(Acct) * MAX_ENTRY);
if (dism2A03 == NULL) {
// Error: We're out of memory.
}
(malloc() returns NULL if there's no more free memory, and the code checks that. Usually all you can do if this happens is terminate the program.)
When you want a new array with some elements removed, then you should back up the starting address of the current one:
Acct* oldArray = dism2A03;
then create a new one with the new size you want:
dism2A03 = malloc(sizeof(Acct) * NEW_SIZE);
if (dism2A03 == NULL) {
// Error: We're out of memory.
}
copy the elements you want from the old array (oldArray) to the new one (dism2A03) - which is up to you, I don't know which ones you want to keep - and after than you must free the old array:
free(oldArray);
As a final note, you might actually not want to create a new array at all. Instead, you could keep having your original, statically allocated array ("statically allocated" means you're not using malloc()):
Acct dism2A03[MAX_ENTRY];
and have a index variable where you keep track of how many useful elements are actually in that array. At first, there are 0:
size_t dism2A03_size = 0;
As you add elements to that array, you do that at the position given by dism2A03_size:
dism2A03[dism2A03_size] = <something>
++dism2A03_size; // Now there's one more in there, so remember that.
While doing so, you need to make sure that dism2A03_size does not grow larger than the maximum capacity of the array, which is MAX_ENTRY in your case. So the above would become:
if (dism2A03_size < MAX_SIZE) {
dism2A03[dism2A03_size] = <something>
++dism2A03_size; // Now there's one more in there, so remember that.
} else {
// Error: the array is full.
}
As you can see, adding something to the end of the array is rather easy. Removing something from the end of the array is just as easy; you just decrement dism2A03_size by one. However, "removing" something from the middle of the array means copying all following elements by one position to the left:
for (size_t i = elem_to_remove + 1; i < dism2A03_size; ++i) {
dism2A03[i - 1] = dism2A03[i];
}
--dism2A03_size; // Remember the new size, since we removed one.
Note that you should not attempt to remove an element if the array is empty (meaning when dism2A03_size == 0.)
There's also the case of adding a new elements in the middle of the array rather than at the end. But I hope that now you can figure that out on your own, since it basically a reversed version of the element removal case.
Also note that instead of copying elements manually one by one in a for loop, you can use the memcpy() function instead, which will do the copying faster. But I went with the loop here so that the logic of it all is more obvious (hopefully.)
when you declare an array in this way Acct dism2A03[MAX_ENTRY]; the array is allocated in the stack, therefore it will be removed when the function will perform the return statement.
What you can do is to allocate the structure in the heap via malloc/calloc, and then you can free that memory area via the free function.
For example :
typedef struct entry Acct;
Acct * dism2A03 = calloc(MAX_ENTRY, sizeof( struct entry));
// ....
free(dism2A03);

Pointer value to variable C

Hi guys I was thinking if I can assign pointer value to variable?
Basically I have pointer that points to integer value and i want to assign it to another variable. Ie:
coursep->node = 1 //coursep is pointer to structure and node is structure variable
int var;
var = coursep->node; //I want variable to be 1
Can I do this? and how? It seems not to work when I try to assign it like this.
EDIT: Basically I am trying to put from pointer value to arrays or structures.
lines = lineCount(courses); //counts how many lines does file have
struct courses course[lines]; // creates array of structures with amount of lines
for (i = 0; i < lines; i++) {
struct courses *coursep;
coursep = course;
fscanf(co, " %c %d ", &coursep->courseName, &coursep->numberOfNodes);
course[i].courseName = coursep->courseName;
course[i].numberOfNodes = coursep->numberOfNodes;
for (j = 0; j < coursep->numberOfNodes; j++) {
fscanf(co, " %d", &(coursep->nodes[j]));
var = *coursep->nodes[j];
printf("%d\t", var);
}
fscanf(co, "\n");
}
Structure:
struct courses{
char courseName;
int numberOfNodes;
int nodes[];
};
I cant seem to put it straight into array, because it prints out random rubbish, if I use pointers it seems to show correct values (everything is read from file), but when I try to put it all into array it seems tho throw random rubbish again =/ any ideas?
When you declare an empty array member at the end of a structure, it is a Flexible array member.
According to ISO/IEC 9899:TC3, Section 6.7.2.1 Structure and union specifiers, Constraint 16
As a special case, the last element of a structure with more than one named member may
have an incomplete array type; this is called a flexible array member. In most situations,
the flexible array member is ignored. In particular, the size of the structure is as if the
flexible array member were omitted except that it may have more trailing padding than
the omission would imply. However, when a . (or ->) operator has a left operand that is
(a pointer to) a structure with a flexible array member and the right operand names that
member, it behaves as if that member were replaced with the longest array (with the same
element type) that would not make the structure larger than the object being accessed; the
offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, it behaves as if it had one element but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past it.
In your case, I don't think it is necessary to use a flexiable array member. You can change the definition of int nodes[] to int* nodes, and allocate memory for nodes in the for loop.
try this
int *var;
var = &coursep->node;
One problem with this code is that coursep always points at the first element of your course array:
struct courses course[lines];
for (i = 0; i < lines; i++) {
struct courses *coursep;
coursep = course;
/* ... */
}
...which means that almost everything in that array will probably be garbage.
You need to change the nodes member variable to be a pointer rather than an array, and also to allocate memory for that array before assigning to it:
struct courses{
char courseName;
int numberOfNodes;
int *nodes;
};
...
course[i].nodes = malloc(sizeof(int) * course[i].numberOfNodes);
(or something like that)

Array object pointers with string assignment causes crash

So I am trying to assign a string value to an object in an array.
The object code is:
typedef struct BiTreeData_ {
char* word;
int start_word_count;
int end_word_count;
int start_ranking;
int end_ranking;
} BiTreeData;
In my main I make an array of pointers to BiTreeData using:
BiTreeData **dataarray;
dataarray=(BiTreeData**)malloc(sizeof(BiTreeData*)*maintree.size);
I try to assign a value to one of the variables within the struct with:
int z = dataarray[i]->start_word_count;
The program crashes. Any help would be appreciated. Thank you.
Your code here
BiTreeData **dataarray;
dataarray=(BiTreeData*)malloc(sizeof(BiTreeData)*maintree.size);
allocates the memory space for an array of BitTreeData* but you are not allocating any space for the BitTreeData objects themselves. You just have a dynamic array of pointers that point to uninitialised memory.
It would probably be far easier if you just create an array of BitTreeData rather than of pointers. You could achieve this by using
BiTreeData *dataarray;
dataarray=(BiTreeData*)malloc(sizeof(BiTreeData)*maintree.size);
This just creates an array of BitTreeData - you can then access each item in the array like you would any other array (remembering now that the array is of BitTreeData not BitTreeData*)
you have to allocate memory for each element in the array of dataarray
dataarray[i] = (BiTreeData *) malloc ((sizeof(BiTreeData)
the followingline code you put
array=(BiTreeData**)malloc(sizeof(BiTreeData*)*maintree.size);
with this code, you have allocated array of pointers. but theses pointers are not pointed to any content yet. so you have to allocate memory for each pointer in the array
Is there a reason you are defining
BiTreeData **dataarray;
To get this to work the way you want I think you need to define it as:
BiTreeData *dataarray;
This will allow you to malloc an array of BiTreeData structs.
To create the array of structs:
BiTreeData *dataarray;
To allocate memory on the heap for the array of structs:
dataarray = malloc(sizeof(BiTreeData)*maintree.size);
To set the value of a struct element in your array:
int z = 5;
dataarray[i].start_word_count = z;
To extract a value from your struct array:
int z = dataarray[i].start_word_count;
Since you're allocating an array of pointers, the size of element should be the size of BiTreeData *, not BiTreeData:
dataarray= (BiTreeData **)malloc(sizeof(BiTreeData *) * maintree.size);
EDIT
The question has since been edited to correct this mistake.

Array of C structs

If I create a struct in C and want to add them to an array that is not set to a fixed size, how is the array created?
Can one create a tempStruct which is used on every iteration while getting user input and store this in an array, always using the same tempStruct struct in the loop?
How is an array created if the size is unknown as it depends on user input, and how are structs added to this array?
When the size is unknown at compile time, you'll need to allocate the memory on the heap, rather than in the data segment (where global variables are stored) or on the stack (where function parameters and local variables are stored). In C, you can do this by calling functions like malloc.
MyStructType *myArray = (MyStructType *)malloc(numElements * sizeof(MyStructType)
... do something ...
free(myArray)
If you're actully using C++, it's generally better to use new[] and delete[], e.g.
MyStructType *myArray = new MyStructType[numElements]
... do something ...
delete [] myArray
Note that new[] must be paired with delete[]. If you're allocating a single instance, use new and delete (without "[]"). delete[] and delete are not equivalent.
Also, if you're using C++, it's generally easier and safer to use an STL vector.
the C array must be with fixed size this is what we have learned years ago
but memory allocation functions may help you to find a solution
in c++ you can use the operator new
int num=0;
cout<<"please enter the number"<<endl;
cin>>num;
int *x=new int[num];
for(int i=0;i<num;i++)
{
cout<<"enter element "<<(i+1)<<endl;
cin>>x[i];
}
//do your work
and as
Mr Fooz
mentioned delete[] is used to free the memory allocated by new[]
and this is a general example
If you are using the older C89 standard compiler, you cannot use variable length arrays. If you use C99 then you can create variable length array. For clarification: variable-lenght doesnt mean that the array lenght can change during execution. It just means that you can set it during execution instead of fixing a value during compile time.
For eg:
CreateArray(const int numberOfElements)
{
struct MyStruct arrayOfStructs[numberOfElements];
}
This is valid in C99 but not in C89. Check your compiler documentaion.
Yes, you can use a tempStruct during input which you add later to the array.
If the size of the array is unknown, then you are in trouble. You must keep track of the array's size somewhere. Just have an integer variable that you change every time you change your array to keep track of your array's size.
If the size of the struct is not known at compile time it is even more complicated. You either just store Pointers in the array which point to your actual struct elements in memory, or you have to keep track of the sizes of every struct in the array. In the later case you would have to do addressing in the array completely manually calculating a lot. While this is very memory efficient, it is also error prone and extremely hard to debug.
OK. sample to create an array that hold your struct using pointers:
struct MyStruct
{
/* code */
}
main()
{
counter = 0;
struct MyStruct** array = malloc(counter);
// Create new Element
struct MyStruct myElement;
myElement.someData = someValue;
// Add element to array:
array = realloc(array, sizeof(struct MyStruct*) * (counter + 1);
array[counter] = &myElement;
counter++;
// Create yet another new Element
struct MyStruct myElement;
myElement.someData = someOtherValue;
array = realloc(array, sizeof(struct MyStruct*) * (counter + 1);
array[counter] = &myElement;
counter++;
// Now remove the last element
free(array[counter -1]); // may have something more complicated than that, depending on your struct
array = realloc(array, sizeof(struct MyStruct*) * (counter - 1);
counter--;
}
this code is not tested!

Assigning an address to a struct pointer array member in C

Having considerable trouble with some pointer arithmatic. I think I get the concepts (pointer variables point to a memory address, normal variables point to data) but I believe my problem is with the syntax (*, &, (*), *(), etc.)
What I want to do is build dynamic arrays of a custom struct (i.e. arrays of pointers to heap structs), and my interface provides two methods, "ad_to_obj_array" (which takes the object to add and the array which can be null for empty) and "obj_array_dustbin" (which just takes the array to dispose, also disposing of the contents, the heap objs). The former is rendered below.
The details of the objects are not important (and the struct has been renamed anyway) but my solution to the general problem is below, and I'd be grateful if you can spot the error. The compiler is complaining about an invalid lvalue, where I try and assign the address in the pointer on the RHS to the pointer value in an array of pointers to heap structs:
#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))
obj* add_to_obj_array(obj* new_obj, obj* array)
{
int number_of_elements = 0;
if (array != NULL)
{
number_of_elements = NUM_ELEM(array);
}
obj* new_array = NULL;
/* note: I am expecting sizeof(new_obj) to return the size of an obj*
to go into the array of pointers. */
if ( NULL ==
(new_array = (obj*)malloc((number_of_elements + 1)* sizeof(new_obj))) )
{
/* memory request refused :( */
return NULL;
}
/* copy the old array pointers into the new array's pointer slots: */
int i;
for (i = 0; i < number_of_elements; i++)
{
&(new_array[i]) = &(array[i]);
}
/* add the new item to the end (assign pointer value directly): */
new_array[number_of_elements] = new_obj;
if (number_of_elements > 0)
{
free(&array);
}
return new_array;
}
Now, I have tried the following permutations of the offending line:
&(new_array[i]) = &(array[i]);
*(new_array[i]) = &(array[i]);
new_array[i] = &(array[i]);
and all give a compiler error of one sort or another. I am fairly sure that the right hand side is the address of the ith element of the old array, but how to I assign to the ith element of the new, when the elements of the array are pointers to structs?
EDIT - please note, the macro NUM_ELEM above DOES NOT WORK; it will always return 1. See #Merlyn Morgan-Graham's answer below for why.
Based on your description, you're starting off wrong, so by the time you get to copying things, nothing you can do is likely to work.
Right now, you've defined new_array (and, presumably, array) as a pointer to obj. The result looks like this:
In this case, you have a pointer to a dynamically allocated array of objects. When/if you expand the allocation, you'll need to copy all the objects themselves.
According to your description: "(i.e. arrays of pointers to heap structs)", what you want is an array of pointers. If you want to allocate that array of pointers automatically, your definition would look like:
obj *array[NUMBER];
My guess is that's not what you want though. Presumably, you want to allocate that array dynamically as well. That would look like this:
In this case, new_array and array will each need to be defined as a pointer to pointer to obj. You'd then allocate an array of pointers (i.e., pointers to as many objs as you want) and have each point point at an obj:
obj **new_array;
// allocate an array of pointers with space to point at more items:
new_array = malloc(sizeof(obj *) * new_elements);
// copy the pointers to the current items to the new array:
for (i=0; i<current_elements; i++)
new_array[i] = array[i];
The advantage of this is that when you do the copying, you only copy pointers, not the objects themselves. Especially with large objects, this can save a substantial amount of effort. The tradeoff is that using an element goes through two levels of indirection intead of one, so the reference may be slower (though rarely much slower, especially on a relatively high-performance processor).
As #rerun already pointed out, in either case you probably want to use realloc. In particular, this might be able to expand an allocation "in place", and avoid copying data as often. Of course, that's not guaranteed, but at least you're giving it a chance; if you malloc and copy every time, you eliminate even the possibility of that optimization.
You have two arrays doesn't new_array[i] = array[i] do what you need.
Have you looked at realloc as a possible solution.
Just assign the values across. new_array[i] = array[i].
The problem you may be running into is that, for obj* to actually be an array of pointers, obj must itself be a pointer type:
typedef struct
{
int value1;
} obj_pool;
typedef obj_pool* obj;
int main(int argc, char* argv[])
{
obj_pool pool1;
pool1.value1 = 5;
obj array[] = { &pool1 };
array[0]->value1 = 16;
return 0;
}
Another problem you'll run into once you get this compiling is that sizeof(array) == sizeof(obj*). NUM_ELEM(array) will always return the same value. This means you'll have to pass a size_t array_size parameter to your function.
in your code elements of the array are not pointers on the structure, they are structure objects. elements of the this array obj** array are pointers on the structure obj.
#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))
void add_to_obj_array(obj* new_obj, obj** array)
{
int number_of_elements = 0;
if (array != NULL)
{
number_of_elements = NUM_ELEM(array);
}
// expand array with one more item
array = (obj**)realloc(array, (number_of_elements + 1) * sizeof(new_obj));
if (array == NULL )
{
/* memory request refused :( */
return;
}
// Put new item at the last place on the array
array[number_of_elements] = new_obj;
}
So here we used matrix (pointer on pointers of the obj structure). When we add new element we simply expand existing array for one place and on that place we put new structure object. There is no need to return value because we operate on the pointers of the objects, and all change is done on actual objects, not on their copies.

Resources