Connecting Tech Pros Worldwide Forums | Help | Site Map

realloc'ing an array of strings

John
Guest
 
Posts: n/a
#1: Nov 14 '05
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[i]=p;
}

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

}




Emmanuel Delahaye
Guest
 
Posts: n/a
#2: Nov 14 '05

re: realloc'ing an array of strings


In 'comp.lang.c', "John" <iamlevi3@hotmail.com> wrote:
[color=blue]
> 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).[/color]

Ok. Starting with fixed size is a good approach. Better to process the points
one by one.
[color=blue]
> 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.[/color]

If you free before use, you cause an undefined behaviour. See my code below.
[color=blue]
> 2) I'm malloc'ing the correct size of each string, but how can I
> dynamically grow plines as needed?[/color]

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

/* empty array */
{
char **pp = NULL;
}
[color=blue]
> 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.[/color]

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.
[color=blue]
> #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[i]=p;
> }
>
> for( i=0; i<10; i++ )
> printf(">>> %s \n",plines[i]);
>
> }[/color]

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[i] = p;
}
}

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

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

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

/* -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/
Prawit Chaivong
Guest
 
Posts: n/a
#3: Nov 14 '05

re: realloc'ing an array of strings


"John" <iamlevi3@hotmail.com> wrote in message news:<YYqdnV2aapNsAkLd4p2dnA@comcast.com>...[color=blue]
> 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.[/color]

I wouldn't free(p), But I would free(plines[whatever]) instead.
[color=blue]
>
> 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.
>[/color]

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


[color=blue]
> 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[i]=p;
> }
>
> for( i=0; i<10; i++ )
> printf(">>> %s \n",plines[i]);
>
> }[/color]
Al Bowers
Guest
 
Posts: n/a
#4: Nov 14 '05

re: realloc'ing an array of strings




John wrote:[color=blue]
> 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.
>[/color]

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[i]);
free(plines[i]);
}
[color=blue]
> 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.
>[/color]

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.[color=blue]
>[/color]
[color=blue]
> 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[i]=p;
> }
>
> for( i=0; i<10; i++ )
> printf(">>> %s \n",plines[i]);
>[/color]

#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[i]);
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[i]);
return;
}

--
Al Bowers
Tampa, Fl USA
mailto: xabowers@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

John
Guest
 
Posts: n/a
#5: Nov 14 '05

re: realloc'ing an array of strings


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" <iamlevi3@hotmail.com> wrote in message
news:YYqdnV2aapNsAkLd4p2dnA@comcast.com...[color=blue]
> 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[i]=p;
> }
>
> for( i=0; i<10; i++ )
> printf(">>> %s \n",plines[i]);
>
> }
>
>
>[/color]


Closed Thread