String Concatenation Using Pointers No strcat()

R

raidvvan

Hi there,

I am having a bit of an issue when trying to concatenate strings using
char * pointers.

Here is what I need:

I need to add a list of ID's to a string that is a SQL statement so
that I can end up with:
SELECT DISTINCT Object_ID FROM Object_Interactions WHERE Object_ID IN
('UUID1', 'UUID2') ORDER BY Object_ID ASC;

Here is what I am doing:

struct object_type
{
char *id; /* UUID = 32 chars length */
};

void strappnd(char *dest, char *src)
{
/* appends one string to another */
while (*src != '\0')
*dest++ = *src++;

*dest = '\0';
}

char *buffer = NULL;
char *sql = NULL;
int j = 0;
int buffer_size = 0;
int object_count = 0;

object_count = 2; /* this is actually a calculated value... */

/* I have used malloc() and then assigned a value to object_list[j]-
id and that was OK */

buffer_size = 32 * object_count + strlen("''") * object_count +
strlen(", ") * (object_count - 1) + 1;

buffer = (char *)malloc(buffer_size * sizeof(char)); /* I know about
pointer casting issue and malloc without stdlib.h but there is too
much code to be changed... */
strcpy(buffer, "");

for (j=0; j<object_count; j++)
{
printf("buffer=%s\n", buffer);

strcat(buffer, "'");
strappnd(buffer, object_list[j]->id);

/* we must not end the sequence with a comma */
if (j < object_count - 1)
strcat(buffer, "', '");
else
strcat(buffer, "'");
}
sql = (char *)malloc((100 + buffer_size + 1) * sizeof(char));
sprintf(sql, "SELECT DISTINCT Object_ID FROM Object_Interactions WHERE
Object_ID IN (%s) ORDER BY Object_ID ASC;", buffer);
free(buffer);

printf("sql=%s\n", sql);

Result:
sql = SELECT DISTINCT Object_ID FROM Object_Interactions WHERE
Object_ID IN (UUID1') ORDER BY Object_ID ASC;

I have been trying and searching for a couple of days for all kinds of
solutions but I can't seem to find anything and I can't make it work.
Basically the question is how to transform a const char * into a char
*. Does simple casting work? Is it safe? What else can I do because
I keep hitting this wall, and I can't use the standard <string.h>
functions because most of them expect a char const * as opposed to
char * in one of the arguments.

I have been looking on the Internet and forums, but for most cases
strcat is being used and seems to be enough.
I found interesting variations of strcat, but they don't seem to work
and I don't have any more time for this. After finding libAPR I even
thought of using it, but I only need one function from this library
and plus the application must be portable on Linux, Mac, Windows...

Any help on how to do string concatenation with char * or how to
convert const char * to char * would be greatly appreciated.

Other than that, C is just great. :)

Thanks very much.
Ovidiu Anghelidi
(e-mail address removed)
 
M

Mark Bluemel

Hi there,

I am having a bit of an issue when trying to concatenate strings using
char * pointers.
[Snip]

void strappnd(char *dest, char *src)
{
/* appends one string to another */
while (*src != '\0')
*dest++ = *src++;

*dest = '\0';
}

This is strcpy() surely?
I have been trying and searching for a couple of days for all kinds of
solutions but I can't seem to find anything and I can't make it work.

Your presentation of the problem is too verbose and ill-formed for me to
make sense of it.

Surely before posting you could have boiled down your problem to a
really simple testcase?

If you simply want to process something like this :-

char *uuids[4] = { "UUID1", "UUID2", "UUID3", "UUID4" };

into

char *all_uuids; /*containing "UUID1, UUID2, UUID3, UUID4" */

What about this :-

#include <stdio.h>
#include <string.h>
int main(void) {
char *uuids[4] = {"UUID1", "UUID2", "UUID3", "UUID4"};
char *all_uuids = malloc(1024); /* arbitrary size
* and needs error check
*/
int i;
for (i = 0; i < 4; i++) {
if (i>0) {
strcat(all_uuids,", ");
}
strcat(all_uuids,uuids);
}
printf("all the uuids are (%s)\n",all_uuids);
}
 
B

Ben Bacarisse

I am having a bit of an issue when trying to concatenate strings using
char * pointers.

Here is what I need:

I need to add a list of ID's to a string that is a SQL statement so
that I can end up with:
SELECT DISTINCT Object_ID FROM Object_Interactions WHERE Object_ID IN
('UUID1', 'UUID2') ORDER BY Object_ID ASC;

Here is what I am doing:

struct object_type
{
char *id; /* UUID = 32 chars length */
};

void strappnd(char *dest, char *src)
{
/* appends one string to another */
while (*src != '\0')
*dest++ = *src++;

*dest = '\0';
}

Basic problem is that you believe the comment not the code. The
above doe snot append. It overwrites.
char *buffer = NULL;
char *sql = NULL;
int j = 0;
int buffer_size = 0;
int object_count = 0;

object_count = 2; /* this is actually a calculated value... */

/* I have used malloc() and then assigned a value to object_list[j]-
id and that was OK */

buffer_size = 32 * object_count + strlen("''") * object_count +
strlen(", ") * (object_count - 1) + 1;

buffer = (char *)malloc(buffer_size * sizeof(char)); /* I know about
pointer casting issue and malloc without stdlib.h but there is too
much code to be changed... */
strcpy(buffer, "");

for (j=0; j<object_count; j++)
{
printf("buffer=%s\n", buffer);

strcat(buffer, "'");
strappnd(buffer, object_list[j]->id);

If you had just gone on to use strcat it would have worked.
/* we must not end the sequence with a comma */
if (j < object_count - 1)
strcat(buffer, "', '");
else
strcat(buffer, "'");
}
sql = (char *)malloc((100 + buffer_size + 1) * sizeof(char));
sprintf(sql, "SELECT DISTINCT Object_ID FROM Object_Interactions WHERE
Object_ID IN (%s) ORDER BY Object_ID ASC;", buffer);
free(buffer);

printf("sql=%s\n", sql);

Result:
sql = SELECT DISTINCT Object_ID FROM Object_Interactions WHERE
Object_ID IN (UUID1') ORDER BY Object_ID ASC;

I have been trying and searching for a couple of days for all kinds of
solutions but I can't seem to find anything and I can't make it work.
Basically the question is how to transform a const char * into a char
*. Does simple casting work?

Yes, but...
Is it safe?
No.

What else can I do because
I keep hitting this wall, and I can't use the standard <string.h>
functions because most of them expect a char const * as opposed to
char * in one of the arguments.

strcat has a const string argument only as the source. Personally, I
would check the UUID lengths before adding them, and advance a buffer
pointer as I went. You'd get some added assurance that you won't
overflow your buffer and you can use strcpy rather than strcat.
Any help on how to do string concatenation with char * or how to
convert const char * to char * would be greatly appreciated.

If you need to, something has probably gone very wrong.
 
R

raidvvan

If you had just gone on to use strcat it would have worked.

I tried that before, but I got segmentation fault and that's why I
thought of replacing it. I will try again with the checking.
If you need to, something has probably gone very wrong.

This is great. I kept thinking that this is the way to go.

Thanks a lot,
Ovidiu
 
K

Keith Thompson

Mark Bluemel said:
What about this :-

#include <stdio.h>
#include <string.h>
int main(void) {
char *uuids[4] = {"UUID1", "UUID2", "UUID3", "UUID4"};
char *all_uuids = malloc(1024); /* arbitrary size
* and needs error check
*/
int i;
for (i = 0; i < 4; i++) {
if (i>0) {
strcat(all_uuids,", ");
}
strcat(all_uuids,uuids);
}
printf("all the uuids are (%s)\n",all_uuids);
}


One problem with that is that strcat() has to scan the target string
each time before appending the new string. For a small number of
short strings like you have here, it's probably not a big deal, but
it's an O(N**2) algorithm for something that can easily be done in
O(N).

An improvement would be to use strcpy() rather than strcat(), and
update a pointer to point to the end of the string after each step.
This still does some unnecessary scanning, but at least it doesn't
re-scan the same string repeatedly.

If you have a fixed number of strings to append, you might consider
sprintf() (though the overhead of processing the format string
might be excessive):
sprintf(all_uuids, "%s, %s, %s, %s",
uuids[0], uuids[1], uuids[2], uuids[3]);

Or you can write your own routine that keeps track of the end of the
string as it goes along.
 
D

Default User

I tried that before, but I got segmentation fault and that's why I
thought of replacing it. I will try again with the checking.

That's the stage at which you should have come to us. You should know
that generally speaking the standard library function WORK. So if you
are having a problem, it's likely a simple case of misuse.

Go back and post that code. We'll fix it and you'll be better off all
around.




Brian
 
R

raidvvan

One problem with that is that strcat() has to scan the target string
each time before appending the new string. For a small number of
short strings like you have here, it's probably not a big deal, but
it's an O(N**2) algorithm for something that can easily be done in
O(N).

strcat() is good enough for what I am doing now
If you have a fixed number of strings to append, you might consider
sprintf() (though the overhead of processing the format string

I don't know how many UUID's are in the array so that's why I am
appending.

Thank you.
 
R

raidvvan

That's the stage at which you should have come to us. You should know
that generally speaking the standard library function WORK. So if you
are having a problem, it's likely a simple case of misuse.

I have got only a few months of C so if there is something wrong, I
always assume I need to expand my view and search for something else.
strcpy and strcat expect const char *, and because I am using char * I
haven't seen too many examples in which you can just pass the char *
pointer to the function. Most examples deal with char []. Plus I don't
feel like wasting someone's else time without doing even a shabby
homework. :)

I can't make any changes right now. I will have to do it tomorrow.

Thank you very much.
 
R

Richard Heathfield

(e-mail address removed) said:
I have got only a few months of C so if there is something wrong, I
always assume I need to expand my view and search for something else.
strcpy and strcat expect const char *,

For the *source*, not the target. And the const is effectively a promise
that strcpy and strcat won't change the data you're copying *from* in the
process of copying that data to the target.
 
D

Default User

I have got only a few months of C so if there is something wrong, I
always assume I need to expand my view and search for something else.

That's a puzzling and usually incorrect view. If you are inexperienced
with a tool, and it doesn't seem to be working, it's not likely that
you need a different tool. You probably need instruction in proper use
of the one you have.
strcpy and strcat expect const char *, and because I am using char *

This makes little sense. The signature for strcpy() is:

char *strcpy(char *destination, const char *source);

Only the source, which you wouldn't want to change anyway, needs to be
const qualified. You don't generally WANT to alter a const-qualified
object. It's bad mojo.

I haven't seen too many examples in which you can just pass the char *
pointer to the function.

You see one up there.
Most examples deal with char [].

This doesn't make sense. You can't pass an array into any function. It
sounds like you need to review the FAQ on arrays and pointers. A
typical use of strcpy() might be:

#include <string.h>


const char *src = "Here's a string!";

char *dest;

dest = malloc(strlen(src)+1;

/* error checking the result of malloc() is vital, but left out here */

strcpy(dest, src);




Brian
 
R

raidvvan

Hello everyone,

Thanks for all your help. The code is working now.

Best regards,
Ovidiu Anghelidi
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top