How to _delete_ element from dynamic array? - c

I have seen other answers to questions like this, but none seemed to work for me. Say I have a dynamic array:
int* myarray;
myarray = malloc(myarray, 4*sizeof(int));
myarray[0] = 1;
myarray[1] = 2;
myarray[2] = 3;
myarray[3] = 4;
What I want to do is to remove (and free, because the array will keep on getting larger and larger) the first element of the array. I am well aware of realloc which removes the last element of the array if shrunk. Any ideas on this? Is this possible?
Thanks in advance!

One method I can think of is doing
memmove(myarray, myarray+1, 3*sizeof(int))
and then use realloc to shrink the array. I'm not sure there are more efficient ways to do this in C.

You have to shunt all the other elements along one. Conceptually, it's like this:
for( int i = 0; i < 3; i++ ) p[i] = p[i+1];
As others have mentioned, memmove is optimized for shifting memory segments that overlap, rather than using the above loop.
Moving data around is still inefficient as your array grows larger. Reallocating an array every time you add an item is even worse. General advice is don't do it. Just keep track of how large your array is and how many items are currently stored in it. When you grow it, grow it by a significant amount (typically you would double the size).
It sounds like you might want a circular queue, where you preallocate the array, and a head and tail pointer chase each other round and round as you push and pop items on.

Typically a "Delete" operation is not possible on an array. Perhaps you want to create and use a linked list?
C++ has its std::vector which supports this. What it would do is to shift elements that come later, forward by 1 element. You could implement this, and call realloc later.
Storing them in reverse is an obvious workaround if only first element needs to be deleted.

I don't think that you'll find a proper/clean way to do that in C. C++ as some lybraries who do that, and almost all the OO oriented languages can do that, but not C. All I can think of is moving memory and, yes, calling realloc, or setting the position you want to free to a known value wich you'll consider empty in a memory re-use policy.
Another way to turn the problem is by a dynamic implementation of the array. DOn't know if you want to go there, but if you do, here's some brief example.
Since you're only saving integers, a struct like this:
typedef struct DynamicArray_st{
int x;
struct DynamicArray_st *next;
}DynamicArray;
Makes it possible to alloc and free elements as the program needs to. It also allows insertion in the middle, begin or end and the same for frees.
The way you'll do it is by saving a pointer to the begin of this dynamic type and then iterate over it.
The problem is that you can't access data by the [] notation. Iterations are necessary wich makes it heavier on processing time.
Besides that, your code would become something like this:
DynamicArray *array = malloc(sizeof(DynamicArray)); /*Just a first element that will stay empty so your Dynamic array persists*/
array->next = NULL;
DynamicArray *aux = array;
DynamicArray *new;
for(i = 0; i<4; i++){
new = malloc(sizeof(DynamicArray));
new->next = NULL;
new->x = i+1;
aux->next = new;
aux = new;
}
Here you have a sequence of structs in a way that each struct points to the next one and has a integer inside.
If now you'd do something like:
aux = array->next; /*array points to that empty one, must be the next*/
while(aux != NULL){
printf("%d\n",aux->x);
aux = aux->next;
}
You'll get the output:
1
2
3
4
And freeing the first element is as easy as:
aux = array->next;
array->next = aux->next;
free(aux);
If you try to draw it(structs are boxes and next/aux/next are arrows) you'll see one boxe's arrow outline an box - the one you want to free.
Hope this helps.

Related

Trying to create an array of node pointers using dynamic memory allocation

I'm currently trying to do something simple, turn my list of nodes into an array of pointers to the nodes, so that I could use it for another functionality.
typedef struct {
int data;
} myNode;
In the function where I'm trying to make my array of node pointers, I write something like (assume I have a list called myList of all the nodes):
myNode** aryPtr = malloc(sizeof(myNode*)) * numItemsInList);
and for each spot, I allocate memory for the pointer doing:
int inc = 0;
int z = 0;
aryPtr[inc] = malloc(sizeof(myNode));
aryPtr[inc] = &(myList[z]);
inc += 1;
z += 1;
I've been trying to do something like this to go about storing the pointers to each of my nodes in an array, but haven't had success and don't entirely understand how to make an array of pointers (using a double pointer). Any help on how to store pointers into a dynamically allocated array of pointers would help a lot.
These two lines are a little problematic:
aryPtr[inc] = malloc(sizeof(myNode));
aryPtr[inc] = &(myList[z]);
The first assignment
aryPtr[inc] = malloc(sizeof(myNode));
allocates memory, and makes aryPtr[inc] point to that memory. But the next assignment
aryPtr[inc] = &(myList[z]);
throws away the result of the malloc call, and reassigns aryPtr[inc] to point somewhere else. That leads to a memory leak.
It's similar to having a simple int variable, and assigning it multiple times:
int a;
a = 5;
a = 10;
And then wonder why a is not equal to 5.
To solve this problem, either drop the first assignment with the malloc and only have
aryPtr[inc] = &myList[z]; // Make aryPtr[inc] point to myList[z]
Or dereference the destination pointer to copy the structure:
aryPtr[inc] = malloc(sizeof(myNode));
*aryPtr[inc] = myList[z]; // Copy the structure itself
Another couple of things:
With the code you show (you really need to provide a proper Minimal, Complete, and Verifiable Example) it looks like you're always using index 0 for both aryPtr and myList. You also use the same index for both aryPtr and myList, so you only need a single variable for that.

Initialising member elements of a dynamically allocated array of structs to zero

I have had a look around but have not been able to find an answer to this question already. I am trying to create a hash table of which each element is a struct. In each struct is a variable to let the program know if the cell has been occupied, for this to work I need to set all of them to zero. The thing is it worked fine but now and then (seemingly randomly) I'd get an access violation. I thought I fixed it but when I come to grow my array the error creeps up again, leading me to believe that I have made an error. My pointer knowledge is not that good at all, so any help would be appreciated. This is what the function looks like:
HashTableCell *initialiseTable(HashTableCell *hashTable, int *tableSizePtr)
{
int i = 0;
int totalSize = *tableSizePtr * sizeof(HashTableCell);
HashTableCell *tempStartingcell;
tempStartingcell = (HashTableCell*)malloc(sizeof(HashTableCell));
*tempStartingcell = *hashTable;
while (i <= *tableSizePtr)
{
/*we keep moving forward, need to use the first entry*/
*hashTable = *(tempStartingcell + (i * sizeof(HashTableCell)));
hashTable->isOccupied = 0;
i++;
}
free(tempStartingcell);
return hashTable;
}
And before I malloced some space for the table and passed it in another function like so:
HashTableCell *hashTable;
hashTable = (HashTableCell*)malloc((sizeof(HashTableCell)*tableSize));
hashTable = initialiseTable(hashTable, tableSizePtr);
The idea is to start at the beginning and move along the correct number of spaces along per iteration of the while loop. When I come to resize I merely make a new array with double the malloced space and pass it to the initialise function but this throws up an access violation error at seemingly random indexes.
I am using VS2015 if that helps anything.
Thank you for your help.
The problem is in this line:
*hashTable = *(tempStartingcell + (i * sizeof(HashTableCell)));
When you are adding an integer to a pointer, C and C++ already take into account the size of the array elements, so you should not multiply with sizeof(HashTableCell), but rather do:
*hashTable = *(tempStartingcell + i);
Otherwise, your extra multiplication will cause an access outside of the tempStartingCell array. It makes even more sense to write it like this:
*hashTable = tempStartingcell[i];
But there is more wrong with your code; if you just want to set isOccupied to zero for each element in hashTable, just do:
void initialiseTable(HashTableCell *hashTable, int tableSize)
{
for (int i = 0; i < tableSize; i++)
hashTable[i].isOccupied = 0;
}

Free array of pointers

I have this test code :
void test2(){
char** twoDArray = (char**)calloc(3,sizeof(char*));
char* element1 = (char*)calloc(3,sizeof(char));
twoDArray[0] = element1;
twoDArray[1] = element1;
twoDArray[2] = element1;
freeArray(twoDArray,3);
}
void freeArray(char** arr,int size){
if(arr!= NULL){
for(int i =0 ;i < size;i++){
if(arr[i] != NULL){
free(arr[i]);
arr[i] = NULL;
}
}
free(arr);
arr = NULL;
}
}
in second iteration of loop in freeArray arr[1] != NULL give 'true' and error occurs, why ? How to properly free such array ?
Do not cast the return value of calloc()!
You are assigning the very same pointer to each element of the array. I don't know why/how you expect it to work (because then you won't have a 2D-like array, since setting one element of a row will change the element at the same column in all other rows too...)
If you still stick to this design, then you should free the inner "array" only once.
But I suspect you wanted to emulate a sane, working, sensible 2D-array. In this case, you have two options:
I. The hackish solution: almost the same as yours, but you need to callocate memory for each row in a separate step, like this:
twoDArray[0] = calloc(3, sizeof(twoDArray[0]));
twoDArray[1] = calloc(3, sizeof(twoDArray[0]));
twoDArray[2] = calloc(3, sizeof(twoDArray[0]));
(or perhaps use a loop... if you know what they are.)
II. The correct solution: why not allocate a continuous block of memory and avoid all superfluous calls to calloc() and all headache as to what and when needs to be free()d? One array -> one allocation, one deallocation:
char (*arr[3]) = calloc(3, sizeof(arr[0]));
// ...
free(arr);
Nice, simple and more maintainable.
If you are going to make the freeArray function, you have to define some rules about what the array must contain. Your implementation of freeArray makes the assumption that each element of the array is pointing to a separately allocated array of characters, however each element of the array is actually pointing to the same array of characters, so you end up trying to free the same array multiple times, which is not valid.
If freeArray's assumptions are correct, then you'll need to modify how you create the array. If freeArray's assumptions are not correct, you'll need to modify freeArray.

Array of structure - memory release in C

I am trying to implement a priority queue based on binary heap using a static array (I will be later using a linked list, just wanted to test first with an array).
typedef struct n
{
int x;
int y;
int size;
double value;
} node;
node arr[100];
int total = 1;
void insertElement(int x, int y, int size, double value)
{
node n;
n.x = x;
n.y = y;
n.size = size;
n.value = value;
arr[total] = n;
if (total > 1)
insertArrange(total);
total += 1;
}
Now in the delete function i will just return the top most node and delete it, then re-arranging the whole heap. Problem is I can not free any memory. Suppose I use
free(&arr[1]);
I am getting pointer being freed was not allocated error. Is this the proper way of implementation? How to tackle memory issues?
I am using Xcode with Apple LLVM 4.2 compiler. This entire thing will be ultimately put into a bigger project in Objective-C but for now I do not want to use NSMutableArray. I want a simple solution in C.
You only need to call free() if you have used malloc() or calloc(). In fact, attempting to free anything else is undefined behaviour.
As it stands, your code will not be leaking any memory.
Why delete? You could just zero it out and write new data to it whenever you need to. Also My recommendation would be to remember which nodes you delete, so that later when you need to insert a new node, you will know beforehand where the free space is.
For example:
node arr[10];
indexes free_index[10];
//(delete the 6th member of nodes)
delete arr[5];
//remember which one you deleted
free_index[0] = 5;
//later when you add new node you can search the index and pick the first matching value
// zero it out so that it will not be used accidentally again like this
int i = free_index[0] // finding which one is free is task for loops
new_node(arr[i]);
free_index[i] = NULL;
This code example here is very incomplete you have to complete it depending on your own implementation. I just gave you the idea. watch out for free_index [0] = 0; it basically will never match as a valid index. If you zero out indexes with = NULL statement.
There is also a big assumption from my side that you do not wish to shrink the size of this array or grow it. Just empty some elements and then add new ones.
If you want to grow the array you have to calloc it first. I advise calloc because you can allocate array of structs with it.
Growing this is easy with realloc.
But with shrinking you need to create temporary array of nodes where you will store all active results, shrink the original array, put the active results from temporary array back into original and free temporary array.
calloc(numberofnodearrays,sizeof(node));

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);

Resources