3

I'm try to concatenate to char * rv with the result of a function call that will return an int. fib() returns an int. The main problem I'm running into is that strcat()'s signature requires a const char * as it's second arg:

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

Here is a small sample of my code. fib() calculates the nth fibonacci number - in this case, the 7th fibonacci number.

char * rv;
int num;

rv = (char*)malloc(2048*sizeof(char));
num = 7;

...

strcat(rv, (const char *)itoa(fib(num), rv,10));

Obviously this is wrong and won't compile. What is the cleanest way to do this? Do I need another char * var to store the results of itoa() first, instead of using rv?

Thank you for any help you can provide!

koopajah
  • 23,792
  • 9
  • 78
  • 104
iaacp
  • 4,655
  • 12
  • 34
  • 39
  • off-topic, but may I suggest `rv = malloc(2048 * sizeof *rv)`; casting malloc's result is pointless in C, and the duplicated typename in the argument is just bitrot waiting to happen when you change types later. – jthill Feb 26 '13 at 17:06

4 Answers4

3

Use snprintf() to construct a buffer containing the int and then concatenate it to your rv buffer. Do not attempt to concatenate the existing content of rv in the same call to snprintf():

snprintf(rv, 2048, "%s%d", rv, itoa(fib(num), rv,10)));

as this means the input and output buffers overlap which is undefined behaviour.

Also:

So the malloc() call would be:

rv = malloc(2048);
if (rv)
{
}
Community
  • 1
  • 1
hmjd
  • 120,187
  • 20
  • 207
  • 252
2

You could do this

sprintf(dest,"%s %d",rv,num);
LtWorf
  • 7,286
  • 6
  • 31
  • 45
2

You need either an intermediate char array to print the number to before strcating, or you can directly sprintf the number to rv, but for that you need a pointer to the end,

char *rv = malloc(2048);
char *rv_end = rv;
...
rv_end += sprintf(rv_end, "%d", fib(num));

and also update the rv_end pointer when appending other things to the buffer.

(Thanks to jthill for the improvement using the return value of sprintf.)

Community
  • 1
  • 1
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • 1
    or `rv_end+=sprintf(rv_end,"%d",fib(num));` – jthill Feb 26 '13 at 17:07
  • Thank you for your response. Let's say I then wanted to append a literal string to rv after your code. Could I just use `sprintf(rv_end, "%s", "Hello World")`? And then update `rv_end += strlen(rv_end);` again? – iaacp Feb 26 '13 at 17:08
  • @iaacp Yes, but it's even better to use jthill's improvement. – Daniel Fischer Feb 26 '13 at 17:09
  • I just want to make sure when I concatenate to `rv` later, that I'm also updating `rv_end` properly. So if I used jthill's method for a literal string, I'd just use `rv_end += sprintf(rv_end, "%s", "Hello!");`, correct? – iaacp Feb 26 '13 at 17:15
  • Correct, @iaacp. But you could also just `strcat` (or `strcpy`) and add the length of the string. If you know the length beforehand, that will probably be more efficient than `sprintf`. – Daniel Fischer Feb 26 '13 at 17:17
1
char * strcat ( char * destination, const char * source );

The "const" on source simply tells the compiler that the strcat function will not modify "source". Otherwise,

strcat(buffer, "hi");

would not be allowed.

This does not mean that your source must be constant, nor should it have the const modifier.

strcat(rv, (char *)itoa(fib(num), rv,10));

(no "const") is perfectly legal and should not generate any compiler warnings.

The only issue is that if you don't know the length of the source, you're opening yourself up to a buffer overflow. In this particular case, you can figure out how long the itoa return can be and size the destination accordingly. However, it's probably safer to us snprintf to control how large it is.

DoxyLover
  • 3,366
  • 1
  • 15
  • 19