tags:

views:

57

answers:

3

For example

sprintf(pos,"%f ",cl.snap.ps.origin[0]); //don't start with strcat
sprintf(tmp,"%f ",cl.snap.ps.origin[1]);strcat(pos, tmp);

fine.

with

sprintf(tmp,"%f ",cl.snap.ps.origin[0]);strcat(pos, tmp);
sprintf(tmp,"%f ",cl.snap.ps.origin[1]);strcat(pos, tmp);

not fine.

+3  A: 

strcat concatenates strings ; which means, it merges the contents of pos and tmp. What does pos contain before you call strcat? Has it been defined?

Jacob
The problem (in documentation of sites such as this http://www.cplusplus.com/reference/clibrary/cstring/strcat/) is that concatenation doesn't mean "1st argument must have a terminating character". You have to explicitly know it. i.e. There's nothing saying that it can be undefined but there's nothing saying it can't be undefined either.Of course I guess, one could go with the rule 'never touch anything even remotely undefined in c'. I guess they should start segfaulting stuff like declarations without definitions and then checking if they're untrue to be more concise..
Lela Dax
+6  A: 

The strcat() function expects that the destination argument already contains a properly null-terminated string. In your case, it sounds like pos contains some junk that looks like a null-terminated string, but isn't what you expect. strcat() is dutifully appending on to the end of that junk.

One way to fix this is to initialise pos before your code:

pos[0] = '\0';
sprintf(tmp,"%f ",cl.snap.ps.origin[0]);strcat(pos, tmp);
sprintf(tmp,"%f ",cl.snap.ps.origin[1]);strcat(pos, tmp);
Greg Hewgill
Another way: `sprintf(pos, "%f %f ", cl.snap.ps.origin[0], cl.snap.ps.origin[1]);`
JeremyP
"strcat() function expects that the destination argument already contains a ". Right, beautiful. Atrocious that manuals don't say that: http://www.cplusplus.com/reference/clibrary/cstring/strcat/ [or if they do, they do a good job at obscuring it]
Lela Dax
From that page: "destination Pointer to the destination array, which should contain a C string".
Greg Hewgill
+1  A: 

Don't use strcat and tmp. You're writing senselessly overcomplicated and inefficient code. Instead:

pos+=sprintf(pos,"%f ",cl.snap.ps.origin[0]);
pos+=sprintf(pos,"%f ",cl.snap.ps.origin[1]);
...

Unless you're sure sprintf cannot fail, rather than directly adding the return value to pos, you should probably first store the return value in a separate int variable and check that it's not -1.

It would also be better to use snprintf to make sure you don't overflow your buffer:

size_t cnt, rem=your_buffer_size;

cnt=snprintf(pos, rem,"%f ",cl.snap.ps.origin[0]);
if (cnt>=rem) goto error;
pos+=cnt; rem-=cnt;

cnt=snprintf(pos, rem,"%f ",cl.snap.ps.origin[1]);
if (cnt>=rem) goto error;
pos+=cnt; rem-=cnt;
...

Note that cnt being an unsigned type (size_t) is critical to the error check working.

R..
Or I could just printf "%f %f %f..
Lela Dax
Indeed. I was thinking more of a general pattern for cases where you can't do that.. perhaps when subsequent appends depend on the results of earlier ones or when you need to use the intermediate string - like testing that a directory is only accessible by the current user before creating a security-critical file in it or something.
R..
Also, since your argument was an array element, it looked like you might actually want to put this code in a loop.
R..