Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

runtime char* arrays

Status
Not open for further replies.

bitwise

Programmer
Mar 15, 2001
269
US
Where have I gone astray?

#include <stdio.h>
int main(int argc, char* argv[])
{
int e, size;
char** cArray;
char buffer[100];

printf(&quot;Enter Size: &quot;);
scanf(&quot;%d&quot;, &size);
(char*)cArray = malloc(size*sizeof(char*));
for(e=0;e<size;e++)
{
printf(&quot;Enter String %d: &quot;, e+1);
scanf(&quot;%s&quot;, buffer);
cArray[e] = buffer;
}

printf(&quot;=== Strings Entered ===\n&quot;);
for(e=0;e<size;e++)
printf(&quot;%s\n&quot;, cArray[e]);
printf(&quot;\n&quot;);


free(cArray);
return(0);
}

Example Run:

prompt$ ./test
Enter Size: 4
Enter String 1: why
Enter String 2: doesn't
Enter String 3: this
Enter String 4: work
=== Strings Entered ===
work
work
work
work

prompt$

What's up with that? Obviously it's not indexing the char* but just assigning cArray to the last given string. In any case how do you manually allocate a runtime array of char* like the char* argv[] which is passed to the program?

Thanks,
bitwise
 
Although you have allocated a array of char *,all elements of the array point to a same address (buffer),So you can only get the last string you enteres(the &quot;work&quot;).
You must allcate memory for each element as below :
...
cArray = malloc(size*sizeof(char*));
for(e=0;e<size;e++) {
printf(&quot;Enter String %d: &quot;, e+1);
cArray[e] = malloca(100 * sizeof(char)); //<----
scanf(&quot;%s&quot;, cArray[e]);
}
...

Hope this helps you! I want to emigrate Canada or Australia. Any relative information you supplied will be appreciated!

zallen@cmmail.com
ICQ:101229409
 
Below is a revised version of your code with comments inline. Hopefully the explanations are clear. The reason that it's printing out &quot;work&quot; for all of your arrays has to do with the fact that you set each pointer in the array of pointers to point to the first element of buffer, in other words all elements of the pointer array end up pointing to the same region of memory (welcome to the wonderful world of pointers :). I would draw a diagram, but I'm just too tired for ASCII art right now.

The code below allocates enough memory for each pointer to hold the string entered into buffer on each iteration and then copies the contents of buffer to the newly allocated memory. If anything's unclear, just post again.

#include <stdio.h>
#include <stdlib.h> /* You need to include this for malloc and free */
#include <string.h> /* for strcpy and strlen */

int main(int argc, char* argv[])
{
int e, size;
char** cArray;
char buffer[100];

printf(&quot;Enter Size: &quot;);
scanf(&quot;%d&quot;, &size);

/* RPB - No need for a cast before cArray here
* This allocates memory for size number of pointers
* to char
*/
cArray = malloc(size * sizeof(char *));

/* RB - added check for malloc failure */
if (cArray!=NULL) {
for(e=0;e<size;e++)
{
printf(&quot;Enter String %d: &quot;, e+1);
/* RB - Added modifier to limit # of characters that can be
* read into buffer
*/
scanf(&quot;%100s&quot;, buffer);
/* RB - This allocates memory for the string just entered */
cArray[e]=malloc(strlen(buffer)+1);
if (NULL==cArray[e]) {
/* handle error */
break;
}
/* Now copy the string over to the position in the array */
strcpy(cArray[e],buffer);
}
/* This part doesn't allow for an error that may have
* occured from malloc above
*/
printf(&quot;=== Strings Entered ===\n&quot;);
for(e=0;e<size;e++) {
printf(&quot;%s\n&quot;, cArray[e]);
free(cArray[e]);
}
free(cArray);
printf(&quot;\n&quot;);

}
return 0;
}





Russ
bobbitts@hotmail.com
 
Thanks guys, it's working now. I just didn't quite understand how to allocate enough memory and make the pointers point to the right locations. One more question though. Why does it only handle strings w/o spaces? For example:

prompt$ ./test
Enter Size: 5
Enter String 1: why does it do this?
Enter String 2: Enter String 3: Enter String 4: Enter String 5: === Strings Entered ===
why
does
it
do
this?

prompt$

Can't scanf() grab a string with spaces? Or is the null terminating char '\0' also considered a space?

Thanks,
bitwise
 
The %s specifier matches a sequence of non-white-space characters, so it stops grabbing characters when it hits a space. For just reading in a line of input, you're much better off with fgets() which stops when it hits a newline:

if (fgets(buffer,sizeof buffer,stdin)==NULL) {
/* fgets() failed */
} else {
char *tmp=strchr(buffer,'\n');
if (tmp==NULL) {
/* Line too long, truncated */
} else {
/* Get rid of newline */
*tmp='\0';
}
}

For more, see man fgets.



Russ
bobbitts@hotmail.com
 
Just to add,

You could force scanf also to accept white spaces like this

scanf(&quot;%[A-Za-z0-9 ]s&quot;, arrayname);

what ever symbol is included within the &quot;[&quot; and &quot;]&quot; will all be accepted. So make the space also a part of the symbols included between &quot;[&quot; and &quot;]&quot;.

You might also try gets() which will accept white spaces.

Regards,
Shiv
 
Just a note on the following:

/* RPB - No need for a cast before cArray here
* This allocates memory for size number of pointers
* to char
*/
cArray = malloc(size * sizeof(char *));

First, a lot of compilers won't *let* you cast the l-value. Second, I was doing something very similar in VC++, and did need to cast to make the compiler happy - otherwise it's trying to set cArray (a char **) to the return of malloc (a void *) soooo I needed

cArray = (char **)malloc(size * sizeof(char*));
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top