I want to create an array of variable size that stores strings of maximum length 40. I have performed research and found the following code,which creates a dynamic array of integers.
typedef struct {
int *array;
size_t used;
size_t size;
} Array;
void initArray(Array *a, size_t initialSize) {
a->array = malloc(initialSize * sizeof(int));
a->used = 0;
a->size = initialSize;
}
void insertArray(Array *a, int element) {
// a->used is the number of used entries, because a->array[a->used ] updates a->used only *after* the array has been accessed.
// Therefore a->used can go up to a->size
if (a->used == a->size) {
a->size *= 2;
a->array = realloc(a->array, a->size * sizeof(int));
}
a->array[a->used ] = element;
}
void freeArray(Array *a) {
free(a->array);
a->array = NULL;
a->used = a->size = 0;
}
I am currently trying to modify the code, to make it work for my problem. I have so far come up with this
typedef struct {
size_t used;
size_t size;
char *array[][40];
} Array;
void initArray(Array *a, size_t initialSize) {
a->array = malloc(initialSize * sizeof(char));
a->used = 0;
a->size = initialSize;
}
void insertArray(Array *a, char element) {
// a->used is the number of used entries, because a->array[a->used ] updates a->used only *after* the array has been accessed.
// Therefore a->used can go up to a->size
if (a->used == a->size) {
a->size *= 2;
a->array = realloc(a->array, a->size * sizeof(char));
}
strcpy(a->array[a->used ], element);
}
Finally
Array a;
char srcname[40];
initArray(&a, 100);
insertArray(&a, srcname);
This produces a segmentation fault. Although I have researched, I have not managed to make a working dynamic array of strings. Any guidance would be appreciated
CodePudding user response:
If you want to store the strings with max length of 40 characters including the terminating null
character, you can use flexible array members. You do not special function to initialize the array, the string adding one will do initialization as well (you only need to pass NULL as a parameter showing that the array was not initialized yet).
The function automatically changes the size of the string array in the steps defined in STEP
macrodefinition.
typedef struct {
size_t used;
size_t size;
char array[][40];
} Array;
#define STEP 64
Array *addString(Array *arr, const char *str)
{
size_t newsize;
if(!arr || arr -> size == arr -> used)
{
newsize = arr ? arr -> size STEP : STEP;
arr = realloc(arr, sizeof(*arr) newsize * sizeof(arr -> array[0]));
arr -> size = newsize;
arr -> used = newsize == STEP ? 0 : arr -> used;
}
if(arr)
{
strncpy(arr -> array[arr -> used], str, sizeof(arr -> array[0]));
arr -> array[arr -> used][sizeof(arr -> array[0]) - 1] = 0;
arr -> used ;
}
return arr;
}
int main(void)
{
Array *arr = NULL, *tmp;
// function wrks same as realloc so you need to assign the temp variable to
// avoid memory leak in case of error. I will skip it for the simplicity of the example
for(size_t i = 0; i < 256; i )
{
char str[40];
sprintf(str,"String no: %zu", i);
arr = addString(arr, str);
printf("Array: size: %3zu used: %3zu\n", arr -> size, arr -> used);
}
for(size_t i = 0; i < 256; i )
{
printf("Array sting no %zu: `%s`\n", i, arr -> array[i]);
}
}
https://godbolt.org/z/8E7EbeaW7
CodePudding user response:
The declaration of the data member array in the structure
typedef struct {
size_t used;
size_t size;
char *array[][40];
} Array;
is incorrect.
If you want to declare a pointer then you need to write
typedef struct {
size_t used;
size_t size;
char ( *array )[40];
} Array;
The function initArray
is also incorrect.
void initArray(Array *a, size_t initialSize) {
a->array = malloc(initialSize * sizeof(char));
a->used = 0;
a->size = initialSize;
}
because there is allocated an incorrect array.
The function can look the following way
int initArray( Array *a, size_t initialSize)
{
a->used = 0;
a->array = malloc( initialSize * sizeof( char[40] ) );
int success = a->array != NULL;
if ( success )
{
a->size = initialSize;
}
else
{
a->size = 0;
}
return success;
}
Correspondingly the function insertArray
(that has an incorrect type of the second parameter because you are going to pass a string not a single character are not you?) should be declared and defined like
int insertArray( Array *a, const char *element )
{
int success = 1;
if ( a->used == a->size )
{
char ( *tmp )[40] = realloc( a->array, 2 * a->size * sizeof( char[40] ) );
if ( ( success = tmp != NULL ) )
{
a->array = tmp;
a->size *= 2;
}
}
if ( success )
{
strcpy( a->array[a->used ], element );
}
return success;
}
And at last the array srcname
char srcname[40];
must contain a string before passing the array to the function insertArray
.