realloc'ing an array of strings

Discussion in 'C Programming' started by John, Jun 28, 2004.

  1. John

    John Guest

    I'm trying (struggling) to use realloc to grow a list of strings. The
    number of strings is not known (this is a subset of an assignment to write a
    recursive ls program... my BS was in EE, so I'm trying to catch up!).

    I'm working on the following program to try to figure this out. Now, I'm at
    the point where I'm filling up plines with (I belive) a list of pointers,
    each of which is pointing to a string ("foo 1", "foo 2", and so forth). The
    hard-coded 10 in the for loop, btw, is only for this exploration of ideas...
    It will not be in the final code (indeed, none of the hard-code numbers will
    be).

    My two sticking points are:
    1) I'm supposed to "free" stuff that I've malloc'd. If I do free(p),
    then the pointers that I've stuffed into plines no longer point to anything,
    and the printout loop at the end of main confirms that when free(p) is in
    place.

    2) I'm malloc'ing the correct size of each string, but how can I
    dynamically grow plines as needed? The realloc man page tells me that I can
    only realloc a thing that got it's address from a prior malloc... but where
    can I malloc plines? It reeks of a chicken/egg situation at 12:30am.

    Any insight or pointers [groan] are certainly appreciated.


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

    char *plines[30];

    int main(void){
    char buf[1024];

    int i;

    for( i=0; i<10; i++ ){
    char temp[1024];
    sprintf(temp,"foo %d",i);

    char *p = malloc( strlen(temp) + 1 );
    strcpy(p,temp);
    plines=p;
    }

    for( i=0; i<10; i++ )
    printf(">>> %s \n",plines);

    }
     
    John, Jun 28, 2004
    #1
    1. Advertising

  2. In 'comp.lang.c', "John" <> wrote:

    > I'm trying (struggling) to use realloc to grow a list of strings. The
    > number of strings is not known (this is a subset of an assignment to
    > write a recursive ls program... my BS was in EE, so I'm trying to catch
    > up!).
    >
    > I'm working on the following program to try to figure this out. Now,
    > I'm at the point where I'm filling up plines with (I belive) a list of
    > pointers, each of which is pointing to a string ("foo 1", "foo 2", and
    > so forth). The hard-coded 10 in the for loop, btw, is only for this
    > exploration of ideas... It will not be in the final code (indeed, none
    > of the hard-code numbers will be).


    Ok. Starting with fixed size is a good approach. Better to process the points
    one by one.

    > My two sticking points are:
    > 1) I'm supposed to "free" stuff that I've malloc'd. If I do
    > free(p),
    > then the pointers that I've stuffed into plines no longer point to
    > anything, and the printout loop at the end of main confirms that when
    > free(p) is in place.


    If you free before use, you cause an undefined behaviour. See my code below.

    > 2) I'm malloc'ing the correct size of each string, but how can I
    > dynamically grow plines as needed?


    Should be a flexible array of pointers to char. The type is char * * (aka
    char **)

    /* empty array */
    {
    char **pp = NULL;
    }

    > The realloc man page tells me that I
    > can only realloc a thing that got it's address from a prior malloc...
    > but where can I malloc plines? It reeks of a chicken/egg situation at
    > 12:30am.


    It also said that realloc() with NULL acts like malloc().

    /* grow to 3 pointers : (FAQ) */
    {
    char **pp = NULL;
    ...
    {
    void *p_tmp = realloc (pp, 3 * sizeof *pp);
    if (p_tmp != NULL)
    {
    pp = p_tmp;
    }
    }
    }

    Note : the 3 pointers are not initialized.

    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <string.h>
    >
    > char *plines[30];
    >
    > int main(void){
    > char buf[1024];
    >
    > int i;
    >
    > for( i=0; i<10; i++ ){
    > char temp[1024];
    > sprintf(temp,"foo %d",i);
    >
    > char *p = malloc( strlen(temp) + 1 );
    > strcpy(p,temp);
    > plines=p;
    > }
    >
    > for( i=0; i<10; i++ )
    > printf(">>> %s \n",plines);
    >
    > }


    Not bad. Here is your code revisited. HTH. Feel free to ask for details.

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

    int main (void)
    {
    int i;

    char *plines[30];

    for (i = 0; i < 10; i++)
    {
    char temp[8]; /* try 4 */

    int n = sprintf (temp, "foo %d", i);

    /* design checker (works in most cases) */
    assert (n < sizeof temp - 1);

    {
    char *p = malloc (strlen (temp) + 1);

    if (p != NULL)
    {
    strcpy (p, temp);
    }
    plines = p;
    }
    }

    for (i = 0; i < 10; i++)
    {
    printf ("[%p] -> '%s'\n", (void *) plines, plines);
    }

    /* free the allocated arrays of char */
    for (i = 0; i < 10; i++)
    {
    free (plines), plines = NULL;
    }

    /* just a checker... */
    for (i = 0; i < 10; i++)
    {
    printf ("[%p]\n", (void *) plines);
    }

    /* -ed- C90 compatibility */
    return 0;
    }

    --
    -ed- get my email here: http://marreduspam.com/ad672570
    The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=c99
    FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
     
    Emmanuel Delahaye, Jun 28, 2004
    #2
    1. Advertising

  3. "John" <> wrote in message news:<>...
    > I'm trying (struggling) to use realloc to grow a list of strings. The
    > number of strings is not known (this is a subset of an assignment to write a
    > recursive ls program... my BS was in EE, so I'm trying to catch up!).
    >
    > I'm working on the following program to try to figure this out. Now, I'm at
    > the point where I'm filling up plines with (I belive) a list of pointers,
    > each of which is pointing to a string ("foo 1", "foo 2", and so forth). The
    > hard-coded 10 in the for loop, btw, is only for this exploration of ideas...
    > It will not be in the final code (indeed, none of the hard-code numbers will
    > be).
    >
    > My two sticking points are:
    > 1) I'm supposed to "free" stuff that I've malloc'd. If I do free(p),
    > then the pointers that I've stuffed into plines no longer point to anything,
    > and the printout loop at the end of main confirms that when free(p) is in
    > place.


    I wouldn't free(p), But I would free(plines[whatever]) instead.

    >
    > 2) I'm malloc'ing the correct size of each string, but how can I
    > dynamically grow plines as needed? The realloc man page tells me that I can
    > only realloc a thing that got it's address from a prior malloc... but where
    > can I malloc plines? It reeks of a chicken/egg situation at 12:30am.
    >


    char **plines = NULL;
    int num_plines = 0;

    int main(void){
    char buf[1024];
    int len;

    while ( your_condition )
    {
    if(!plines)
    plines = malloc (sizeof(char*) * ++num_plines );
    else
    plines = realloc( plines, sizeof(char*) * ++num_plines );

    assert(plines);

    sprintf(buf,"foo%d",num_plines); // It will start from foo1,if you want
    // to start from zero, change it.
    len = strlen(buf) + 1;
    char *p = malloc(len);
    memcpy(p,buf,len);
    plines[num_plines-1] = p;
    }

    ....
    ....
    ....
    } // main



    > Any insight or pointers [groan] are certainly appreciated.
    >
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <string.h>
    >
    > char *plines[30];
    >
    > int main(void){
    > char buf[1024];
    >
    > int i;
    >
    > for( i=0; i<10; i++ ){
    > char temp[1024];
    > sprintf(temp,"foo %d",i);
    >
    > char *p = malloc( strlen(temp) + 1 );
    > strcpy(p,temp);
    > plines=p;
    > }
    >
    > for( i=0; i<10; i++ )
    > printf(">>> %s \n",plines);
    >
    > }
     
    Prawit Chaivong, Jun 28, 2004
    #3
  4. John

    Al Bowers Guest

    John wrote:
    > I'm trying (struggling) to use realloc to grow a list of strings. The
    > number of strings is not known (this is a subset of an assignment to write a
    > recursive ls program... my BS was in EE, so I'm trying to catch up!).
    >
    > I'm working on the following program to try to figure this out. Now, I'm at
    > the point where I'm filling up plines with (I belive) a list of pointers,
    > each of which is pointing to a string ("foo 1", "foo 2", and so forth). The
    > hard-coded 10 in the for loop, btw, is only for this exploration of ideas...
    > It will not be in the final code (indeed, none of the hard-code numbers will
    > be).
    >
    > My two sticking points are:
    > 1) I'm supposed to "free" stuff that I've malloc'd. If I do free(p),
    > then the pointers that I've stuffed into plines no longer point to anything,
    > and the printout loop at the end of main confirms that when free(p) is in
    > place.
    >


    The simple solution would free the allocations when you are finished
    with them. So, change the printf loop to:

    for( i=0; i<10; i++ )
    {
    printf(">>> %s \n",plines);
    free(plines);
    }

    > 2) I'm malloc'ing the correct size of each string, but how can I
    > dynamically grow plines as needed? The realloc man page tells me that I can
    > only realloc a thing that got it's address from a prior malloc... but where
    > can I malloc plines? It reeks of a chicken/egg situation at 12:30am.
    >


    Instead of using char *plines[30], which fixes the max number of
    strings you can allocate to 30, use char **. You can make a struct
    that has a char ** member that points to the array and have another
    member that keeps the count of the number of elements(strings)
    allocated. You can write functions that manipulate this struct;
    functions such as AddString, PrintStr, FreeStr. See the example.
    >


    > char *plines[30];
    >
    > int main(void){
    > char buf[1024];
    >
    > int i;
    >
    > for( i=0; i<10; i++ ){
    > char temp[1024];
    > sprintf(temp,"foo %d",i);
    >
    > char *p = malloc( strlen(temp) + 1 );
    > strcpy(p,temp);
    > plines=p;
    > }
    >
    > for( i=0; i<10; i++ )
    > printf(">>> %s \n",plines);
    >


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

    struct sarray
    {
    char **line;
    unsigned count;
    };

    int AddString(struct sarray *p, const char *s);
    void FreeString(struct sarray *p);
    void PrintString(struct sarray *p);

    int main(void)
    {
    char buf[1024];
    struct sarray mytest = {NULL}; /* Empty array */
    int i;

    for( i=0; i<10; i++ )
    {
    sprintf(buf,"foo %d",i);
    AddString(&mytest, buf);
    }
    PrintString(&mytest);
    FreeString(&mytest);
    return 0;
    }

    int AddString(struct sarray *p, const char *s)
    {
    char **tmp;

    if((tmp = realloc(p->line,
    (p->count+1)*(sizeof *tmp))) == NULL)
    return 0;
    if(tmp)
    {
    p->line = tmp;
    if((p->line[p->count] = malloc(strlen(s)+1)) == NULL)
    return 0;
    strcpy(p->line[p->count++],s);
    }
    return 1;
    }

    void FreeString(struct sarray *p)
    {
    unsigned i;

    for(i = 0; i < p->count;i++)
    free(p->line);
    free(p->line);
    p->line = NULL;
    p->count = 0;
    return;
    }

    void PrintString(struct sarray *p)
    {
    unsigned i;

    for(i = 0;i < p->count;i++)
    printf("%6u: %s\n",i+1,p->line);
    return;
    }

    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
     
    Al Bowers, Jun 28, 2004
    #4
  5. John

    John Guest

    Ahh... All the responses to my op were extremely helpful, and I've got
    something going now. I think that one of the main sticking points for me
    was the idea data being stored in an unnamed chunk of memory (i.e., no
    variable name). But i suppose that the name isn't really necessary, as long
    as the memory is set aside for it and the data can be access.



    "John" <> wrote in message
    news:...
    > I'm trying (struggling) to use realloc to grow a list of strings. The
    > number of strings is not known (this is a subset of an assignment to write
    > a recursive ls program... my BS was in EE, so I'm trying to catch up!).
    >
    > I'm working on the following program to try to figure this out. Now, I'm
    > at the point where I'm filling up plines with (I belive) a list of
    > pointers, each of which is pointing to a string ("foo 1", "foo 2", and so
    > forth). The hard-coded 10 in the for loop, btw, is only for this
    > exploration of ideas... It will not be in the final code (indeed, none of
    > the hard-code numbers will be).
    >
    > My two sticking points are:
    > 1) I'm supposed to "free" stuff that I've malloc'd. If I do free(p),
    > then the pointers that I've stuffed into plines no longer point to
    > anything, and the printout loop at the end of main confirms that when
    > free(p) is in place.
    >
    > 2) I'm malloc'ing the correct size of each string, but how can I
    > dynamically grow plines as needed? The realloc man page tells me that I
    > can only realloc a thing that got it's address from a prior malloc... but
    > where can I malloc plines? It reeks of a chicken/egg situation at
    > 12:30am.
    >
    > Any insight or pointers [groan] are certainly appreciated.
    >
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <string.h>
    >
    > char *plines[30];
    >
    > int main(void){
    > char buf[1024];
    >
    > int i;
    >
    > for( i=0; i<10; i++ ){
    > char temp[1024];
    > sprintf(temp,"foo %d",i);
    >
    > char *p = malloc( strlen(temp) + 1 );
    > strcpy(p,temp);
    > plines=p;
    > }
    >
    > for( i=0; i<10; i++ )
    > printf(">>> %s \n",plines);
    >
    > }
    >
    >
    >
     
    John, Jun 29, 2004
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Martin Eyles

    Parse-ing Strings

    Martin Eyles, Jan 12, 2006, in forum: ASP .Net
    Replies:
    10
    Views:
    691
    Martin Eyles
    Jan 19, 2006
  2. Newsgroup Posting ID

    passing 2d array and realloc

    Newsgroup Posting ID, Sep 17, 2003, in forum: C Programming
    Replies:
    2
    Views:
    1,016
    Dave Thompson
    Sep 22, 2003
  3. Ben

    Strings, Strings and Damned Strings

    Ben, Jun 22, 2006, in forum: C Programming
    Replies:
    14
    Views:
    814
    Malcolm
    Jun 24, 2006
  4. J. Sharp
    Replies:
    0
    Views:
    3,172
    J. Sharp
    Jul 15, 2009
  5. J. Sharp

    open()ing strings as filehandles

    J. Sharp, Jul 16, 2009, in forum: Perl Misc
    Replies:
    2
    Views:
    174
    Xho Jingleheimerschmidt
    Jul 17, 2009
Loading...

Share This Page