c wrote:
Quote:
Hi everybody.
>
I'm working on converting a program wriiten on perl to C, and facing a
problem with concatenate strings.
Now here is a small program that descripe the problem, if you help me
to solve in this small code, I can solve it on my own program...you
don't want to have head-ache :-)
>
So, the problem excatly is, I built an array..just like this one.
>
char *my_array [10];
my_array[0] = "Sally\n";
my_array[1] = "Ndiya\n";
my_array[2] = "Samantha\n";
my_array[3] = "Sara\n";
my_array[4] = "Cadillac\n";
my_array[5] = "GM For Ever\n";
my_array[6] = "SlacWare\n";
my_array[7] = "Google\n";
my_array[8] = "Google more and more\n";
my_array[9] = "You\n";
my_array[10] = "Computers\n";
"Just like" this one? Including the attempt to store a
value in the non-existent eleventh element of a ten-element
array? In C an array of N elements has indices that run from
[0] through [N-1], inclusive, but does not have an [N] element.
By the way, C offers a more convenient syntax for array
initialization:
char *my_array[10] = { "Sally\n", "Ndiya\n", "Samantha\n",
"Sara\n", "Cadillac\n", "GM For Ever\n", "SlacWare\n",
"Google\n", "Google more and more\n", "You\n",
"Computers\n", };
A few points about this: First, since you've declared the array
to have ten elements but actually provided eleven initializers,
the compiler will complain and point out your mistake. Second,
you could replace [10] with [] and let the compiler figure out
the array size by counting the initializers itself instead of
making you do it (sizeof my_array / sizeof my_array[0] will then
tell you how big the compiler decided the array should be). And
last, the comma after the final initializer is optional -- it's
sometimes convenient if the code is being generated by a program
or if you anticipate adding more initializers later, but you can
use it or omit it according to your own taste.
Quote:
my program will recieve an argument -char *argv[]- from the user.
>
int main(int argc,char *argv[])
>
I want to concatenate the given argument to at the first of each line
of my array. [...]
You need to confront the simplicity of C's memory management.
I mean "simplicity" in the sense that C doesn't do very much about
memory management on its own; you must attend to it for yourself.
This is both a weakness and a strength of C: It's a weakness because
it forces you to fret about the details, and a strength because it
doesn't burden you with the machinery of automatic managers whose
style may not suit your needs.
In this case, C has already done some minimal memory management
for you: It has set aside space for the array my_array and filled
its elements with pointers to strings, and it has set aside space
for those strings and filled them with their intended contents. But
now you need something different: You need to create new strings in
memory someplace, and change the array elements to point to those
new strings instead of the old ones.
Here's a quickie solution, with explanation to follow:
for (i = 0; i < sizeof my_array / sizeof my_array[0]; ++i) {
char *new;
new = malloc(strlen(argv[1]) + strlen(my_array[i]) + 1);
if (new == NULL)
exit (EXIT_FAILURE);
strcpy (new, argv[1]);
strcat (new, my_array[i]);
my_array[i] = new;
}
The first line steps the variable i through all the valid index
values of the array my_array, executing the body of the loop once
for each i value. The second line declares a temporary variable called
new that will point to the memory for one of the new strings you're
about to create -- you can't just obliterate my_array[i] yet, because
you still need to work with the original string it's still pointing to.
The third line requests some memory to be allocated. How much?
You'll need enough for all the characters of the argv[1] string, plus
enough for all the characters of the my_array[i] string, plus one more
for the '\0' that must be present at the end of any string. (It is
astonishing how frequently people forget about that "plus one;" be
on guard against making that all-too-commmon mistake.)
The fourth and fifth lines are important: You call malloc to
*request* a certain amount of memory, but the request might not be
granted. Perhaps the system is running low on memory, perhaps it
has plenty available but it's all scattered around in dribs and
drabs none of which are big enough, perhaps the phase of the Moon
is wrong. *Always* check for a NULL return from malloc, and take
corrective action if you get one -- in this case, the "corrective
action" is simply to terminate the program unsuccessfully, but in
other programs you might do something more elaborate.
The sixth and seventh lines build the new string from the two
pieces. Line six copies the argv[1] string into the new memory area,
and line seven appends the my_array[i] string to it. Note carefully
that line six uses strcpy and seven uses strcat; it would be wrong
to interchange them or to use the same function (either one) in both
places. You need to copy the first string into the uninitialized
brand-new memory area, and then append the second.
Finally, line eight changes my_array[i] so it now points to the
newly-built string.
At the beginning of the program, you'll need to #include the
<string.hheader (to declare the strlen, strcpy, and strcat functions)
and the <stdlib.hheader (for malloc, exit, and EXIT_FAILURE). You
may need other headers like <stdio.hif you intend to display any
results. Also, it would be a good idea for your program to check
that it actually received an argument string (check for argc>1)
before running blindly ahead and trying to do things with a string
that doesn't even exist.
--
Eric Sosman
esosman@acm-dot-org.invalid