Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > realloc'ing an array of strings

Reply
Thread Tools

realloc'ing an array of strings

 
 
John
Guest
Posts: n/a
 
      06-28-2004
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]);

}



 
Reply With Quote
 
 
 
 
Emmanuel Delahaye
Guest
Posts: n/a
 
      06-28-2004
In 'comp.lang.c', "John" <(E-Mail Removed)> 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[i]=p;
> }
>
> for( i=0; i<10; i++ )
> printf(">>> %s \n",plines[i]);
>
> }


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/
 
Reply With Quote
 
 
 
 
Prawit Chaivong
Guest
Posts: n/a
 
      06-28-2004
"John" <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> 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[i]=p;
> }
>
> for( i=0; i<10; i++ )
> printf(">>> %s \n",plines[i]);
>
> }

 
Reply With Quote
 
Al Bowers
Guest
Posts: n/a
 
      06-28-2004


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[i]);
free(plines[i]);
}

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


#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: http://www.velocityreviews.com/forums/(E-Mail Removed) (remove the x to send email)
http://www.geocities.com/abowers822/

 
Reply With Quote
 
John
Guest
Posts: n/a
 
      06-28-2004
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" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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]);
>
> }
>
>
>



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Strings, Strings and Damned Strings Ben C Programming 14 06-24-2006 05:09 AM
Nesting an array of strings inside a array of structures Amit Limaye C++ 4 04-10-2006 06:21 PM
Catching std::strings and c-style strings at once Kurt Krueckeberg C++ 2 11-17-2004 03:53 AM
How do copy Strings from a single dimensional array to double dimensional array Venkat C++ 4 12-05-2003 09:23 AM
Comparing strings from within strings Rick C Programming 3 10-21-2003 09:10 AM



Advertisments