1

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...

0

2 Answers 2

2

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
Sign up to request clarification or add additional context in comments.

Comments

2
  1. use strlen(str) instead of sizeof(str) for calculating the string length.
root[files_i]= malloc(strlen(str) + 1); // +1 for null character at the end of the string
if(!root[file_i]) {return;}
  1. if you want to copy string, use strcpy instead of using = operator. Or use strdup (if you use strdup, you do not need to allocate memory for character pointer).
strcpy(root[files_i],str); // copy string str to "file_i" position of array root
  1. if you use the global counter file_i, you should use realloc for root, because the size of root has to be vary (i think it's typo, the i++ should change to file_i++ ?).
root= realloc(root, sizeof(char *) * (file_i + 1));
// do not forget to check the return value of malloc or realloc function.
if(!root) {return;}
  1. Do not cast malloc or realloc function. See at Do I cast the result of malloc?

1 Comment

You were right and clear on everything, i really appreciate your help and i understood a lot of this topic. Thank you very much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.