Click here to Skip to main content
14,699,322 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm writing my second "C" program and would like to solve the following issue:

I have a struct as follows:

struct ST {
  char *sFile;
  FILE *pfFile;
  char** arsFileData;
} _st1, _st2;


The variable "arsFileData" in the struct is an array or strings and the size is not known until run time. The only way that I have been able to initialize it thus far is as follows:

char* arsFile1Data[iLineTot1];
_st1.arsFileData = arsFile1Data;


"arsFile1Data" is used to store text lines from a file. I use malloc to allocate memory for each line.

How can I create the array in one line rather than create a separate variable first?

What I have tried:

Searched online and here and experimented without success.
Posted
Updated 15-Oct-20 11:00am

_st1.arsFileData = (char**)malloc(iLineTot1 * sizeof(char*));
   
To add to what the others have said, don't do this:
char* arsFile1Data[iLineTot1];
_st1.arsFileData = arsFile1Data;
Since that code is executed in a function, the array of pointers to your strings is created on the stack, and the space is released and reused immediately your function ends. That's OK - but a bad practice - in the main function, but can cause some very odd bugs in other functions which are spectacularly hard to track down. The technical term is a dangling reference or dangling pointer[^]

Instead, you need to allocate space on the heap using malloc as shown by Richard, and then use malloc again to create each individual string:
int iLineTot1 = 2;
_st1.arsFileData = (char**) malloc(iLineTot1 * sizeof(char*));
_st1.arsFileData[0] = (char*) malloc(sizeof(char) * 10);
_st1.arsFileData[1] = (char*) malloc(sizeof(char) * 16);
   
v2
Comments
Brian Oh 15-Oct-20 21:33pm
   
Thanks. I accepted Richard's because it was first and I'm handling the rest OK. Additional details noted though.
Quote:
How can I create the array in one line rather than create a separate variable first?
You cannot: the array is a separate variable.
The ST.arsFile1Data pointer is created when you instantiate the struct and afterwards its value is changed to point the array memory area.
   
v2
You can allocate the array in one line of code but it requires additional code to load the array. Richard's post shows how to allocate memory for the array. Here is a code snippet that can help you load the array.
struct ST
{
    char * sFile;
    FILE * pfFile;
    int    lineCount;
    int    maxLines;
    char** arsFileData;
};

void InitializeStructure( struct ST * pst, int lines )
{
    pst->arsFileData = (char **) malloc( lines * sizeof(char*) );
    pst->maxLines = lines;
    pst->lineCount = 0;
    pst->sFile = NULL;
    pst->pfFile = NULL;
}

void ReleaseStructure( struct ST * pst )
{
    int x;
    for( x = 0; x < pst->lineCount; ++x )
         free( pst->arsFileData[ x ] );
    free( pst->pst->arsFileData );
}

void AddTextLine( struct ST * pst, const char * text )
{
    int index = pst->lineCount;
    if( index >= pst->maxLines )
        return;    // request exceeds available storage

    pst->arsFileData[ index ] = strdup( text );
    ++pst->lineCount;
}
I included a function to free the allocated memory because well-behaved software always cleans up after itself. To use it you could do this :
struct ST st1;

InitializeStructure( & st1, 128 );    // initialize to expected number of entries

AddTextLine( & st1, "this" );
AddTextLine( & st1, "that" );
AddTextLine( & st1, "other" );
AddTextLine( & st1, "who" );
AddTextLine( & st1, "what" );
AddTextLine( & st1, "when" );
AddTextLine( & st1, "where" );
AddTextLine( & st1, "why" );

// do something with st1 here

ReleaseStructure( & st1 );       // release allocated memory
   
v2
Comments
Brian Oh 15-Oct-20 21:43pm
   
Thanks for the info. I accepted Richard's because it was first and I'm handling the rest OK and in a similar way, but additional info is noted.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900