Search code examples
carraysmemory-managementappendc-strings

Create a 2d array of strings using dynamically allocation in c


I have to store some strings given in the args of a c code. I iterate over them but I can't store them properly because I don't know the length of those and neither their number. The better method should be a 2d array of pointers, so I can dynamically allocate memory for every new string. The problem is that I'm new on c and I have a lot of confusion about that technique. I tried to initialize a double pointer and use a function to insert elements, it allocates space for another column(new string) and set the length(size of string).

char** files;
int files_i=0;

void insert(char** root,char[] str)
{
    root=(char **)malloc(sizeof(char *));
    root[files_i]=(char *)malloc(sizeof(char)*sizeof(str));
    root[files_i*sizeof(str)]=str;
    i++;
} 

I pass to the function the double pointer and the string I need to "append". It's not working and I have also really big doubts on how to iterate over that...


Solution

  • What you need is the following

    char **files = NULL;
    size_t files_i = 0;
    
    //...
    
    int insert( char ***root, const char str[], size_t i )
    {
        char *p = malloc( strlen( str ) + 1 );
    
        int success = p != NULL;
    
        if ( success )
        {
            char **tmp = realloc( *root, ( i + 1 ) * sizeof( char * ) );
    
            if ( success )
            {
                strcpy( p, str );
                tmp[i] = p;
                *root = tmp;
            }
            else
            {
                free( p );
            }
        }
    
        return success;
    }
    

    and then in the caller you can write for example

    if ( insert( &files, some_string, files_i ) ) ++files_i;
    

    Here is a demonstrative program.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int insert( char ***root, const char str[], size_t i )
    {
        char *p = malloc( strlen( str ) + 1 );
    
        int success = p != NULL;
    
        if ( success )
        {
            char **tmp = realloc( *root, ( i + 1 ) * sizeof( char * ) );
    
            if ( success )
            {
                strcpy( p, str );
                tmp[i] = p;
                *root = tmp;
            }
            else
            {
                free( p );
            }
        }
    
        return success;
    }
    
    int main(void) 
    {
        char **files = NULL;
        size_t files_i = 0;
    
        if ( insert( &files, "Hello", files_i ) ) ++files_i; 
        if ( insert( &files, "World", files_i ) ) ++files_i; 
    
        for ( size_t i = 0; i < files_i; i++ )
        {
            puts( files[i] );
        }
    
        for ( size_t i = 0; i < files_i; i++ )
        {
            free( files[i] );
        }
        free( files );
    
        return 0;
    }
    

    Its output is

    Hello
    World