Remove element from c array - c

I need to remove a specific element from an array, that array is dynamically resized in order to store an unknown number of elements with realloc.
To control the allocated memory and defined elements, I have two other variables:
double *arr = NULL;
int elements = 0;
int allocated = 0;
After some elements being placed in the array, I may need to remove some of them. All texts that I've found says to use memmove and reduce the variables by the number of elements removed.
My doubt is if this method is secure and efficient.

I think this is the most efficient function you can use (memcpy is not an option) regarding secured - you will need to make sure that the parameters are OK, otherwise bad things will happen :)

Using memmove is certainly efficient, and not significantly less secure than iterating over the array. To know how secure the implementation actually is, we'd need to see the code, specifically the memmove call and how return results from realloc are being checked.
If you get your memmove wrong, or don't check any realloc returns, expect a crash.

In principle, assuming you calculate your addresses and lengths correctly, you can use memmove, but note that if you overwrite one or more elements with the elements at higher indexes, and these overwritten elements were structs that contained pointers to allocated memory, you could produce leaks.
IOW, you must first take care of properly disposing the elements you are overwriting before you can use memmove. How you dispose them depends on what they represent. If they are merely structs that contain pointers into other structures, but they don't "own" the allocated memory, nothing happens. If the pointers "own" the memory, it must be deallocated first.

The performance of memmove() and realloc() can be increased by data partitioning. By data partitioning I mean to use multiple array chunk rather than one big array.
Apart from memmove(), I found memory swaping is efficient way. But there is drawback. The array order may be changed in this way.
int remove_element(int*from, int total, int index) {
if(index != (total-1))
from[index] = from[total-1];
return total-1; // return the number of elements
}
Interestingly array is randomly accessible by the index. And removing randomly an element may impact the indexes of other elements as well. If this remove is done in a loop traversal on the array, then the reordering may case unexpected results.
One way to fix that is to use a is_blank mask array and defer removal.
int remove_element(int*from, int total, int*is_valid, int index) {
is_blank[index] = 1;
return total; // **DO NOT DECREASE** the total here
}
It may create a sparse array. But it is also possible to fill it up as new elements are added in the blank positions.
Again, it is possible to make the array compact in the following efficient swap algorithm.
int sparse_to_compact(int*arr, int total, int*is_valid) {
int i = 0;
int last = total - 1;
// trim the last blank elements
for(; last >= 0 && is_blank[last]; last--); // trim blank elements from last
// now we keep swapping the blank with last valid element
for(i=0; i < last; i++) {
if(!is_blank[i])
continue;
arr[i] = arr[last]; // swap blank with the last valid
last--;
for(; last >= 0 && is_blank[last]; last--); // trim blank elements
}
return last+1; // return the compact length of the array
}
Note that the algorithm above uses swap and it changes the element order. May be it is preferred/safe to be used outside of some loop operation on the array. And if the indices of the elements are saved somewhere, they need to be updated/rebuilt as well.

Related

Sorting integer array by ascending order, segmentation fault: 11

The function is suppose to sort an array of random integers by ascending order. I found a method for solving this problem, the bubble sort, swaping a by b if b < a. However, my implementation, or the lack of it, keeps returning a segmentation fault: 11. Could it have something to do with the parameter "int *tab" or subscripts I'm using during the swaping of elements?
void ft_sort_integer_table(int *tab, int size)
{
int i;
int j;
int t;
i = 1;
j = 0;
t = 0;
while (tab[j] != '\0')
{
if (tab[i] < tab[j])
{
t = tab[i];
tab[i] = tab[j];
tab[j] = t;
}
i++;
j++;
}
}
Unless you are guaranteed beforehand that the value 0 terminates your buffer and doesn’t appear elsewhere in the array (like you are with null terminated strings) you can’t test for tab[i] being zero to determine that you have reached the end of the array. Your function takes size as a parameter too; why not use that?
EDIT: Also, no sorting algorithm runs in O(n). Bubble sort, which looks like what you’re trying to implement, requires two nested loops.
Skipping the correctness of this implementation of the sorting algorithm (as it seems wrong) the segmentation is caused by the null termination check that you are doing. The NULL('\0') character is specified for strings, or char array types in C programming language, and it is used to signal their termination. It doesn't work with int type arrays. You should be using the size argument for iterating the array.
You do not use the size parameter. Instead you are trying find the null-terminator which int array is not supposed to have (unlike C-string). So in case you have to compare j with size and keep swapping till the array is fully sorted.
Also, it is better of using size_t size instead of int size in order to stay pedantic.
You pass an array and a size to your sorting function but do not use the size anywhere so potentially i and j could go out of bounds causing undefined behavior.
An int array can contain 0s so you need to have other criteria for when your sorting is finished. E.g. when you go through all the elements in the array [0..size] and do not do a swap - then it is sorted.
Firstly, your while loop logic is wrong. The character '\0' refers to the null character at the end of string. This doesn't make sense if you compare it with int type.
Secondly, the logic you implemented is comparing side by side elements of an array and not a single element with all others and placing it. I would recommend you study bubble sort. Geekforgeeks is the best source for cse guys. Hope it solves. Cheers !! Feel free to ask questions

How to save memory in an array of which many elements are always 0?

I have a 2tensor in C that looks like:
int n =4;
int l =5;
int p =6;
int q=2;
I then initialize each element of T
//loop over each of the above indices
T[n][l][p][q]=...
However, many of them are zero and there are symmetries such as.
T[4][3][2][1]=-T[3][4][2][1]
How can I save memory on the elements of T which are zero? Ideally I would like to place something like NULL in those positions so they use 0 instead of 8 bytes. Also, later on in the calculation I can check if they are zero or not by checking if they are equal to NULL
How do I implicitly include those symmetries in T with using excess memory?
Edit: the symmetry can perhaps be fixed with a different implementation. But what about the zeros? Is there any implementation to not have them waste memory?
You cannot influence the size of any variable by a value you write to it.
If you want to save memory you have not only to not use it, you have to not define a variable using it.
If you do not define a variable, then you have to not use it ever.
Then you have saved memory.
This is of course obvious.
Now, how to apply that to your problem.
Allow me to simplify, for one because you did not give enough information and explanation, at least not for me to understand every detail. For another, to keep the explanation simple.
So I hope that it suffices if I solve the following problem for you, which I think is kind of the little brother of your problem.
I have a large array in C (not really large, lets say N entries, with N==20).
But for special reasons, I will never need to actually read and write any even indices, they should act as if they contain 0, but I want to save the memory used by them.
So actually I want to only use M of the entries, with M*2==N.
So instead of
int Array[N]; /* all the theoretical elements */
I define
int Array[M]; /* only the actually used elements */
Of course I cannot access any of the elements which are not needed and it will not really be necessary.
But for the logic of my program, I want to be able to program as if I could access them, but be sure that they will always every only read 0 and ignore any written value.
So what I do is wrapping all accesses to the array.
int GetArray(int index)
{
if (index & 1)
{
/* odd, I need to really access the array,
but at a calculated index */
return Array[index/2];
} else
{
/* even, always 0 */
return 0;
}
}
void SetArray(int index, int value)
{
if (index & 1)
{
/* odd, I need to really access the array,
but at a calculated index */ */
Array[index/2] = value;
} else
{
/* even, no need to store anything, stays always "0" */
}
}
So I can read and write as if the array were twice as large, but guarantee not to ever use the faked elements.
And by mapping the indices as
actualindex = wantindex / 2
I ensure that I do not access beyond the size of the actually existing array.
Porting this concept now to the more complicated setup you have described is your job. You know all the details, you can test wether everything works.
I recommend to extend GetArray() and SetArray() by checks on the resulting index, to make sure that it is never outside of the actual array.
You can also add all kinds of self checks to verify that all your rules and expectations are met.

Is it good practise to include an index for an array in C?

I have an array in C that stores strings, and I need to be able to dynamically append to this array. Is it good practise to store the index of this array in a separate variable, or is there some better way to do this? Here's my code.
First defining these variables
char x[10][10];
int x_index = 0;
Adding strings to this array
strcpy(x[x_index], "hello");
x_index += 1;
strcpy(x[x_index], "world");
x_index += 1;
You should call the index the length of the array, because what it is: It is the number of valid entries in the array. There are other entries, but they shouldn't be accessed.
It is not only good practice, but in the most cases necessary to keep track of the current size. Otherwise, how would you know ehere to append the next item? In C, this must be done with an extra variable. (Make sure that you can see that array and length belong together with a consistent nomenclature.)
Make sure that the length doesn't exceed the size of the array, 10 in your example. Often, you have to track both, the length and the size, where the size can be a compile-time constant
if (xlen < XSIZE) strcpy(x[xlen++], str);
(You must also take care not to overflow the 10-character buffer, of course.)
For arrays in which you need to parse every element anyways (and only parse, with no insertion), it is better to put a special value at the end of the array, such as '\0' in char arrays in order to tell the parsing loop when to stop.

How to fill in array gaps when an element is removed?

Lets say I have an array of pointers to some object.
foo* bar[256];
and lets say it contains a list of all the blitted(blitting) textures to my buffer. I then request to take something off the array via deletion, and the thing I am taking off is NOT at the end, right. So there is an empty sort of gap in the array
(filled memory), (empty), (filled memory), (filled memory), etc
While I guess in this example it doesn't really matter, but how would I take every entry in the array that is ahead of the empty space and sort of press it back so the empty space is on the end?
Sorry about the poor wording, friends!
Shifting all the items takes time. If the order of the items doesnt matter I suggest shift only the last item to fill the gap and hold a size int to specify the occupied size.
You should hold it in a struct
typedef struct{
int occupied;
foo* bar[256];
}
lets say we want to delete the k'th cell:
delete(myStruct.bar[k]);
myStruct.bar[k] = myStruct.bar[myStruct.occupied--];
Let's say for example, that you know bar[128] is empty.
The following loop will shift all the elements after bar[128] to the left by one, and thus leave the empty space at the end:
for (int k = 129; k < 128; k++) {
bar[k-1] = bar[k];
}
It is definitely possible to generalize this to more than one gap in your array, but that becomes a little bit more complicated.
int i, j;
for (i=0; i<256; i++) {
if (!(bar[i])) {
for (j=i; j<255; j++) {
bar[j] = bar[j+1];
}
}
}
There is no other way to do that than going through each element in the array that'S above the gap and sort it. If this happens very often, it can become a performance issue. Maybe you should try another data structure, like a linked list. There each element has a pointer to it's next element. Now when you remove one element in the middle of the list, you just have to point the element before the removed one to the element that was next to the removed one - that's it, now your list is sorted again.

C - How can I sort and print an array in a method but have the prior unsorted array not be affected

This is for a Deal or No Deal game.
So in my main function I'm calling my casesort method as such:
casesort(cases);
My method looks like this, I already realize it's not the most efficient sort but I'm going with what I know:
void casesort(float cases[10])
{
int i;
int j;
float tmp;
float zero = 0.00;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
if (cases[i] < cases[j])
{
tmp = cases[i];
cases[i] = cases[j];
cases[j] = tmp;
}
}
}
//Print out box money amounts
printf("\n\nHidden Amounts: ");
for (i = 0; i < 10; i++)
{
if (cases[i] != zero)
printf("[$%.2f] ", cases[i]);
}
}
So when I get back to my main it turns out the array is sorted. I thought void would prevent the method returning a sorted array. I need to print out actual case numbers, I do this by just skipping over any case that is populated with a 0.00. But after the first round of case picks I get "5, 6, 7, 8, 9, 10" printing out back in my MAIN. I need it to print the cases according to what has been picked. I feel like it's a simple fix, its just that my knowledge of the specifics of C is still growing. Any ideas?
Return type void has nothing to do with prevention of array from being sorted. It just says that function does not return anything.
You see that the passed array itself is affected because an array decays to a pointer when passed to a function. Make a copy of the array and then pass it. That way you have the original list.
In C, arrays are passed by reference. i.e. they're passed as pointer to the first element. So when you pass cases into your function, you're actually giving it the original array to modify. Try creating a copy and sorting the copy rather than the actual array. Creating a copy wouldn't be bad as you have only 10 floats.
Instead of rolling your own sort, consider using qsort() or std::sort() if you are actually using c++
There are 2 obvious solutions. 1) Make a copy of the array and sort the copy (easy, waste some memory, likely not a problem these days). 2) Create a parallel array of integers and perform an index sort, i.e., instead of sorting thing original, you sort the index and then dereference the array using the index when you want the sorted version, otherwise by the raw unsorted array.
Well, make a local copy of you input and sort it. Something like this:
void casesort(float cases[10])
{
float localCases[10];
memcopy(localCases, cases, sizeof(cases));
...
Then use localCases to do your sorting.
If you don't want the array contents to be affected, then you'll have to create a copy of the array and pass that to your sorting routine (or create the copy within the routine itself).
Arrays Are Different™ in C; see my answer here for a more detailed explanation.

Resources