Home > Mobile >  Delete the last value of dynamically allocated array in C
Delete the last value of dynamically allocated array in C

Time:10-19

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 and capacity = 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 call realloc
  • 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
}
  •  Tags:  
  • c
  • Related