0

I have a problem trying to create a variable size array that contains strings. I have tried to create a multidimensional array, but it's too difficult. Example:

char *audio_types[8][40];           // 8 is number of string elements in the array by default; 40 is the maximum length of a string
audio_types = (char *) malloc(15);  // increasing number of strings in the array

free(audio_types);

Moreover, I was trying to create variable size pointer array. Example:

char *audio_types[40];              // 40 is the maximum length of a string
*audio_types = (char *) malloc(8);  // setting number of strings to 8

free(audio_types);

The problem is that I don't know how to create an array with variable number of string elements properly. Sorry, I am new in C programming. In the short, my code has to hold multiple string elements in one array. Example:

audio_types[0]  // some string...
audio_types[1]  // another string...
audio_types[2]  // more another sting... etc.

Hope you understand what I am trying to ask. Thank you for your attention.

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • `char* audio_types[40];` declares an "array of 40 (char*)". Compare with `char[40]* audio_types` which is "a pointer to (char[40])". Often, it would be written simply as `char** audio_types`, accepting the array decay to "a pointer to pointers-to-characters (ie. a pointer to strings)". – user2864740 Jun 03 '21 at 21:49
  • `malloc(15);` allocates 15 bytes. If you want 15 pointers `audio_types = malloc(15 * sizeof(char *));` And don't cast the return value of malloc: https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – Jerry Jeremiah Jun 03 '21 at 21:52
  • If you allocate a fixed size array you can't change it. So instead use malloc right from the start and then call realloc to change the size. – Jerry Jeremiah Jun 03 '21 at 21:53
  • `char *audio_types[8][40];` is a 2D array of 320 character pointers. What you meant to write was `char *audio_types[8];` which is 8 character pointers. The 40 is not needed here because the pointers in the array don't point anywhere yet - the 40 is used whe nyou create the strings that the pointers point to. – Jerry Jeremiah Jun 03 '21 at 21:55
  • And `*audio_types = (char *) malloc(8);` doesn't work because `*audio_types` is one character and not a pointer and you are assigning an 8 byte character array to a single character. Your compiler probably printed a warning that you were doing something illegal. You probably wanted `audio_types = malloc(8 * sizeof(char *));` – Jerry Jeremiah Jun 03 '21 at 21:57
  • `char *audio_types[40]; // 40 is the maximum length of a string` a pointer doesn't have a maximum size What you have made here is an array of 40 character pointers. `char audio_types[40];` is an array of 40 characters and can store a single string up to 40 character but you can't change the maximum size like you can with malloc. – Jerry Jeremiah Jun 03 '21 at 22:03

4 Answers4

2

Maybe something like this. It will grow the size of the array when you add new types. It will also keep track of how many types you have in the array (it is needed if you resize the array dynamically and you need to know how many elements are in this array).

#define AUDIO_TYPE_LENGTH 40

typedef char audio_type[AUDIO_TYPE_LENGTH];

typedef struct
{
    size_t size;
    audio_type audio_types[];
}audioTypes_t;

audioTypes_t *AddType(audioTypes_t *types, const char *type)
{
    size_t size = types ? types -> size : 0;

    types = realloc(types, sizeof(*types) + (size + 1) * sizeof(types -> audio_types[0]));

    if(types)
    {
        strncpy(types -> audio_types[size], type, sizeof(types -> audio_types[0] - 1));
        types -> audio_types[size][sizeof(types -> audio_types[0] - 1)] = 0; //making strncpy safe
        types -> size = size + 1;
    }
    return types;
}
0___________
  • 60,014
  • 4
  • 34
  • 74
1

You cannot change the size of an array in C. You could create a new array each time you want to resize and transfer the contents from the old array to the new one. Alternatively, you could use a list to store your strings.

0

When you define the array ( the char *audio_types[40]; line) in C it creates a contiguous block of memory to the 40 char pointers in the array. As memory is allocated when the array is defined you cannot make the array longer. To do that you would need a List data type, or you could create a new array when you want to add a new element which is the old one with the new element at the end.

0

char string[40] is an array of 40 characters that can hold 39 characters maximum (plus the string terminator) - the maximum size cannot be changed and 40 bytes of memory are used even if you store a short string containing 2 characters (plus the string terminator).

char *string is a pointer to some characters - the pointer can point anywhere: to a single character or any size array of characters. If it points to an array of characters (which you can make using malloc() then it can be thought of as a "string")

char *array[8] is an array of 8 "strings" (really it is 8 pointers to characters) The size of the array cannot be changed but the pointers can point anywhere: to a single character or any size array of characters. If the pointers point to an array of characters (which you can make using malloc() then they can be thought of as "strings")

char array[8][40] is a 2D array which you can think of as an array of 8 "strings" - where "strings" is defined as an array of 40 characters that can hold 39 characters maximum (plus the string terminator). You cannot change the size of either dimension.

char **array is a pointer to a char * - which could just be a single "string" or to an array of "strings". The sizes aren't fixed and can be dynamically created.

char *string1 = "asd"; means that string1 points to an array of 4 characters ("asd" plus the string terminator) that are in read-only memory - you cannot change the contents of the string but you can point string1 anywhere you want.

char string1[] = "asd"; means that string1 is an array of 4 characters that are filled up by the compiler with 4 characters ("asd" plus the string terminator) - you can change the contents of the array but you can't change the size.

So if you want a dynamically sized array of character strings you can do this:

#include <stdio.h>  // printf
#include <stdlib.h> // malloc, realloc, free
#include <string.h> // strcpy, strdup

int main()
{
    // make an array of 8 string pointers
    int original_size = 8;
    char **array = malloc(original_size * sizeof(char *));
    
    // point each pointer to a string
    // you don't have to do this all at once if you don't want to
    for (int i=0; i<original_size; i++)
        array[i] = malloc(40 * sizeof(char)); // max of 39 plus the terminator
    
    // array[7] is already allocated so we can just use it as a string
    strcpy(array[7],"asd"); // the last string that we malloced
    
    // reallocate the array to be bigger
    int new_size = 15;
    array = realloc(array, new_size * sizeof(char *));

    // array[14] is a pointer that doesn't point anywhere
    // so we need to allocate space before filling it in
    array[14] = strdup("qwe"); // points 3 characters plus the string terminator
    
    printf("%s\n",array[7]);
    printf("%s\n",array[14]);
    
    // free the one we made with strdup
    free(array[14]);
    
    // free the 8 we malloced
    for (int i=0; i<original_size; i++)
        free(array[i]);
    
    // now free the array we malloced and then realloced
    free(array);
    
    return 0;
}

Note: there is NO error checking in that program because I didn't want to mask the basic ideas - make sure you add error checking to any program you make

Try it at https://onlinegdb.com/XQeyOGd0C

Jerry Jeremiah
  • 9,045
  • 2
  • 23
  • 32