The question is in the title
void deleteLastValue(dynIntArray* t){ //function should responds to unexpected values
if(t->tab == NULL){ //if the array is empty we should return an error
fprintf(stderr,"The array is empty");
exit(1);
}
t->tab[(t->size)-1] = 0; /**I'm not sure what to do here should I free the pointer using free function**/
//t->tab[(t->size)-1] = NULL; is it necessary ?
//free(t->tab[(t->size)-1]);
t->tab = (int*)realloc(t->tab,((t->size)-1)*sizeof(int)); //we reallocate but with the new size
t->size--;//size - 1; but capacity stills the same
}
typedef struct{ //structure of an dynamic array
int * tab; //an array of
unsigned int capacity; // the space in memory
unsigned int size;// size of array
} dynIntArray;
If you can review my code, I had issues with what to do with the last element of the array. And should I do more if I want the program to respond to unexpected inputs to make it work properly. Thank you. You are awesome!
CodePudding user response:
As you realloc
every time, you only need the size of the array. You can also use a flexible array simplifying the allocation and deallocation.
typedef struct{ //structure of an dynamic array
unsigned int size;// size of array
int tab[]; //an array of
} dynIntArray;
dynIntArray *deleteLastValue(dynIntArray* t)
{
if(t && t -> size)
{
t = realloc(sizeof(*t) (t -> size - 1) * sizeof(t -> tab[0]));
if(t) t -> size--;
}
return t;
}
CodePudding user response:
Apparenty it's not quite clear to you how capacity
and size
are related.
realloc
can be a pretty expensive function that may take quite some time. So if you call realloc
each and every time the size changes your code will work, but it might be pretty slow. Therefore the capacity
is used.
Roughly it is done like this:
- You initialize the dynamic array with a
size
= 0 andcapacity
= 100 (or some appropriate value larger than 0). - Now you can add 100 elements to the array without
realloc
ever being called. - If you add one element more, you add 100 to
capacity
and you callrealloc
- Now the capacity is 200 and you can add another 100 elements without
realloc
being called.
If you want to decrease the size of the dynamic array, you just can decrease size
without calling realloc
leaving capacity
alone.
If the difference between size
and capacity
becomes larger than some value or maybe if the capacity
is larger than twice the size
, then you can decrease the capacity and call realloc
There are several strategies about how size
and capacity
are related and when to increase/decrease capacity
.
void deleteLastValue(dynIntArray* t) {
if (t->tab == NULL) {
fprintf(stderr, "The array is empty");
exit(1);
}
t->size--; // that's all you need to do
// now optionally you might want to decrease the capacity
// if the capacity is larger than twice the size
// or based on some other strategy
if (t->capacity > 2 * t->size)
{
t->capacity = t->size;
t->tab = realloc(t->tab, t->capacity);
if (t->tab == NULL) {
fprintf(stderr, "realloc error in deleteLastValue");
exit(1);
}
}
}
Be aware that you still need to check if the array is empty (IOW if size
is 0. I leave this as an exercise.
If you want more information, you should show us the other functions.
Review of your function:
void deleteLastValue(dynIntArray* t) {
if (t->tab == NULL) {
fprintf(stderr, "The array is empty");
exit(1);
}
t->tab[(t->size) - 1] = 0; // this is useless, the element is no longer part of the array
// you don't need to overwrite it with 0
// the call to free below is completly wrong, t->tab[(t->size) - 1] is not a pointer but an int
// free(t->tab[(t->size) - 1]);
// this reallocation is correct (except there is no error checking and the (int*) cast is useless)
t->tab = (int*)realloc(t->tab, ((t->size) - 1) * sizeof(int));
t->size--;
// you leave the capacity alone which is maybe what you want
}