Reputation: 463
I built a dynamically allocated array in C based on the struct
typedef struct Array
{
int capacity;
int original_capacity;
int count;
char **elements;
// element* elements; // TODO - make this work in place of the above
} Array;
with a bunch of different methods (below). It is by design an array of strings (char**s). Everything works perfectly and makes sense as is.
I'm told it's possible to make it an array containing multiple types by use of a union.
How would we go about making our dynamic array be able to handle multiple types in a single instance? Hint: we'll probably want to make use of [C unions]
I have never used unions before and I can't find much online to help me for the specific use case I need.
I created this union, as I think it's what's necessary.
typedef union
{
float f;
int i;
long l;
char c;
char* s;
} element;
And I inserted it into the struct, swapping these lines:
// char **elements; // The string elements contained in the array
element* elements; // TODO - make this work in place of the above
As I think that's where it goes.
I compiled it to see what would happen. I got a lot of incompatible type compiler errors.
I was wondering if I'm on the right track. How you would go about using unions to make an array of multiple types? I suspect it might not require that many changes to the code, but if it is a big project, I'm happy to start from scratch and just build a few functions for it.
I am just looking for a few pointers, methods or considerations to get on the right track. Something in me suspects not a lot of refactoring is required, but maybe there is.
Methods:
Array *create_array(int capacity);
void destroy_array(Array *arr);
char *arr_read(Array *arr, int index);
void arr_append(Array *arr, char *element);
void arr_insert(Array *arr, char *element, int index);
void arr_remove(Array *arr, char *element);
int arr_clear(Array *arr);
char* arr_pop(Array *arr);
int arr_pop_no_rtn(Array *arr);
int arr_copy(Array *src);
int arr_index(Array *arr, char *element);
int arr_reverse(Array *arr);
int arr_sort(Array *arr);
int arr_pop_by_index(Array *arr, int index);
int arr_extend(Array* arr, Array* arr2);
EDIT: Some of my compile errors include:
arrays.c:218:39: error: incompatible types when assigning to type ‘element’ from type ‘void *’
218 | arr->elements[arr->count - 1] = NULL;
| ^~~~
arrays.c: In function ‘arr_clear’:
arrays.c:278:37: error: incompatible types when assigning to type ‘element’ from type ‘void *’
278 | arr->elements[arr->count - 1] = NULL;
| ^~~~
arrays.c: In function ‘arr_pop_no_rtn’:
arrays.c:289:37: error: incompatible types when assigning to type ‘element’ from type ‘void *’
289 | arr->elements[arr->count - 1] = NULL;
| ^~~~
arrays.c: In function ‘arr_pop’:
arrays.c:304:51: error: incompatible type for argument 1 of ‘strlen’
304 | int last_element_length = strlen(arr->elements[last_index]);
| ~~~~~~~~~~~~~^~~~~~~~~~~~
| |
| element
Upvotes: 0
Views: 737
Reputation: 144780
You can implement your variant arrays with a pointer to an array of element
elements, or you can use a union of pointers to the possible element types, which would be more efficient in terms of storage.
In both cases, you should store the type of the elements somewhere.
You did not post the code for the various functions in your API, but much work seems required to handle the various types you declared in the element
union.
Upvotes: 2