0

I want to create an array of string like:

{{"zero","zero"},
{"zero","one"},
{"one","zero"},
{"one","one"}}

If I am not wrong I need 3D array. How can I create it with using dynamic memory allocation and how to return it from function? I mean how is my function should be (char ***getString etc...) and in my main function, how can I use it? Is char ***string = getstring(); work?

I didn't get I have to use 3d array yet, I tried it with 2 mallocs. I create string of array in function like

char** editKeys = malloc(128 * sizeof(char*));
for (int i = 0; i < 128; i++ )
{
    editKeys[i] = (char*) calloc(2, sizeof(char));
}

and it works in function. After that I calledmy function from main like

char **editFile=getEditFile();
printf("%s",editFile[0][0]);

at this point I failed and now I can't be sure is it 2d or 3d and my brain is failed me too. Can't think how can I turned it in 3d array.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • What did you try so far? What didn't work? – Blaze Sep 12 '19 at 14:35
  • Have you done any effort before posting your question? If yes, Please edit your question with more details about the problem you're facing – XBlueCode Sep 12 '19 at 14:40
  • Actually I didn't get I have to use 3d array, I tried it with 2 mallocs. I create string of array in function like ```c char** editKeys = malloc(128 * sizeof(char*)); for (int i = 0; i < 128; i++ ) {editKeys[i] = (char*) calloc(2, sizeof(char)); } ``` and it works in function. After that I calledmy function from main like ```c char **editFile=getEditFile(); printf("%s",editFile[0][0]); ``` at this point I failed and now I can't be sure is it 2d or 3d and my brain is failed me too. Can't think how can I turned it in 3d array. –  Sep 12 '19 at 14:48
  • 3
    Please post a [mre] – klutt Sep 12 '19 at 14:54
  • Don't cast the result of a call to `calloc()` etc. - it is unnecessary and can mask the serious error of a missing prototype. – mlp Sep 12 '19 at 17:22

1 Answers1

0

If your compiler supports variable length arrays then you can allocate the array the following way

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void f( size_t n1, size_t n2, size_t n3, char s[n1][n2][n3] )
{
    for ( size_t i = 0; i < n1; i++ )
    {
        if ( i < n1 / 2 )
        {
            strcpy( s[i][0], "zero" );
        }
        else
        {
            strcpy( s[i][0], "one" );
        }

        if ( i % 2 == 0 )
        {
            strcpy( s[i][1], "zero" );
        }
        else
        {
            strcpy( s[i][1], "one" );
        }
    }
}

int main(void) 
{
    enum { N1 = 4, N2 = 2, N3 = 5 };
    char ( *p )[N2][N3] = malloc( sizeof( char[N1][N2][N3] ) );

    f( N1, N2, N3, p );

    for ( size_t i = 0; i < N1; i++ )
    {
        printf( "\"%s\" \"%s\"\n", p[i][0], p[i][1] );
    }

    free( p );

    return 0;
}

The program output is

"zero" "zero"
"zero" "one"
"one" "zero"
"one" "one"

Or you can indeed allocate an array of arrays of arrays.

For example

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void f( char ***s, size_t n1, size_t n2, size_t n3 )
{
    for ( size_t i = 0; i < n1; i++ )
    {
        if ( i < n1 / 2 )
        {
            strcpy( s[i][0], "zero" );
        }
        else
        {
            strcpy( s[i][0], "one" );
        }

        if ( i % 2 == 0 )
        {
            strcpy( s[i][1], "zero" );
        }
        else
        {
            strcpy( s[i][1], "one" );
        }
    }
}

int main(void) 
{
    enum { N1 = 4, N2 = 2, N3 = 5 };
    char ***p  = malloc( N1 * sizeof( char ** ) );

    for ( size_t i = 0; i < N1; i++ )
    {
        p[i] = malloc( N2 * sizeof( char * ) );
        for ( size_t j = 0; j < N2; j++ )
        {
            p[i][j] = malloc( N3 );
        }
    }

    f( p, N1, N2, N3 );

    for ( size_t i = 0; i < N1; i++ )
    {
        printf( "\"%s\" \"%s\"\n", p[i][0], p[i][1] );
    }


    for ( size_t i = 0; i < N1; i++ )
    {
        for ( size_t j = 0; j < N2; j++ )
        {
            free( p[i][j] );
        }

        free( p[i] );
    }

    free( p );

    return 0;
}

Atain the program output is

"zero" "zero"
"zero" "one"
"one" "zero"
"one" "one"

There is also a third approach where the number of pointers can be less than in the last case. All you need is to allocate a one dimensional array of pointers to first elements of two dimensional arrays.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum { N1 = 4, N2 = 2, N3 = 5 };

void f( char ( **s )[N3], size_t n1 )
{
    for ( size_t i = 0; i < n1; i++ )
    {
        if ( i < n1 / 2 )
        {
            strcpy( s[i][0], "zero" );
        }
        else
        {
            strcpy( s[i][0], "one" );
        }

        if ( i % 2 == 0 )
        {
            strcpy( s[i][1], "zero" );
        }
        else
        {
            strcpy( s[i][1], "one" );
        }
    }
}

int main(void) 
{
    char ( **p )[N3]  = malloc( N1 * sizeof( char ( * )[N3] ) );

    for ( size_t i = 0; i < N1; i++ )
    {
        p[i] = malloc( N2 * sizeof( char[N3] ) );
    }

    f( p, N1 );

    for ( size_t i = 0; i < N1; i++ )
    {
        printf( "\"%s\" \"%s\"\n", p[i][0], p[i][1] );
    }


    for ( size_t i = 0; i < N1; i++ )
    {
        free( p[i] );
    }

    free( p );

    return 0;
}

And at last (I hope) there is a forth approach to declare at first an array of pointers to arrays.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum { N1 = 4, N2 = 2, N3 = 5 };

void f( char * ( *s )[N2], size_t n1, size_t n3 )
{
    for ( size_t i = 0; i < n1; i++ )
    {
        if ( i < n1 / 2 )
        {
            strcpy( s[i][0], "zero" );
        }
        else
        {
            strcpy( s[i][0], "one" );
        }

        if ( i % 2 == 0 )
        {
            strcpy( s[i][1], "zero" );
        }
        else
        {
            strcpy( s[i][1], "one" );
        }
    }
}

int main(void) 
{
    char * ( *p )[N2]  = malloc( N1 * sizeof( char * [N2] ) );

    for ( size_t i = 0; i < N1; i++ )
    {
        for ( size_t j = 0; j < N2; j++ )
        {
            p[i][j] = malloc( N3 * sizeof( char ) );
        }           
    }

    f( p, N1, N3 );

    for ( size_t i = 0; i < N1; i++ )
    {
        printf( "\"%s\" \"%s\"\n", p[i][0], p[i][1] );
    }


    for ( size_t i = 0; i < N1; i++ )
    {
        for ( size_t j = 0; j < N2; j++ ) free( p[i][j] );
    }

    free( p );

    return 0;
}

If the compiler indeed supports variable length array then the first approach is the best.

Note: In the approaches sometimes some parameter as for example n2 is not used because I knwo that it is equal to 2. But in general it should be specified.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335