56

I want to append two strings. I used the following command:

new_str = strcat(str1, str2);

This command changes the value of str1. I want new_str to be the concatanation of str1 and str2 and at the same time str1 is not to be changed.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Udara S.S Liyanage
  • 6,189
  • 9
  • 33
  • 34

10 Answers10

79

You need to allocate new space as well. Consider this code fragment:

char * new_str ;
if((new_str = malloc(strlen(str1)+strlen(str2)+1)) != NULL){
    new_str[0] = '\0';   // ensures the memory is an empty string
    strcat(new_str,str1);
    strcat(new_str,str2);
} else {
    fprintf(STDERR,"malloc failed!\n");
    // exit?
}

You might want to consider strnlen(3) which is slightly safer.

Updated, see above. In some versions of the C runtime, the memory returned by malloc isn't initialized to 0. Setting the first byte of new_str to zero ensures that it looks like an empty string to strcat.

Community
  • 1
  • 1
Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
  • 14
    `malloc` can always return rubbish, and it does even on modern systems. `calloc` gives you zeroed memory. – Kornel Dec 22 '12 at 23:32
  • 2
    And calloc also often takes sizeof(space) time to do it. If you're doing lots of strings and you're careful with your pointers, you can save a lot of redundant instructions. – Charlie Martin Dec 24 '12 at 04:01
  • 2
    Please remove the incorrect conjecture: "I believe the newer C spec actually requires malloc to do so". Also, setting the first byte to zero MAKES it a zero-length string by definition (not looks like). – Michael Labbé May 24 '16 at 06:07
  • Makes the *memory* look like an empty string. The memory returned by malloc, referred to by a `void *`, isn't anything -- by definition. – Charlie Martin May 24 '16 at 13:24
13

do the following:

strcat(new_str,str1);
strcat(new_str,str2);
Xantium
  • 11,201
  • 10
  • 62
  • 89
VirtualTroll
  • 3,077
  • 1
  • 30
  • 47
7

Consider using the great but unknown open_memstream() function.

FILE *open_memstream(char **ptr, size_t *sizeloc);

Example of usage :

// open the stream
FILE *stream;
char *buf;
size_t len;
stream = open_memstream(&buf, &len);

// write what you want with fprintf() into the stream
fprintf(stream, "Hello");
fprintf(stream, " ");
fprintf(stream, "%s\n", "world");

// close the stream, the buffer is allocated and the size is set !
fclose(stream);
printf ("the result is '%s' (%d characters)\n", buf, len);
free(buf);

If you don't know in advance the length of what you want to append, this is convenient and safer than managing buffers yourself.

Christophe Quintard
  • 1,858
  • 1
  • 22
  • 30
  • 2
    It‘s worth noting that `open_memstream` is part of POSIX, not the ISO C standard. It is thus not available on non-Unix systems such as Windows, and not even on all Unix ones. `strcat` is a more portable solution. – Denis Washington Dec 30 '21 at 10:46
1

You'll have to strncpy str1 into new_string first then.

Xantium
  • 11,201
  • 10
  • 62
  • 89
Joel Falcou
  • 6,247
  • 1
  • 17
  • 34
0

You could use asprintf to concatenate both into a new string:

char *new_str;
asprintf(&new_str,"%s%s",str1,str2);
frmdstryr
  • 20,142
  • 3
  • 38
  • 32
0

I write a function support dynamic variable string append, like PHP str append: str + str + ... etc.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

int str_append(char **json, const char *format, ...)
{
    char *str = NULL;
    char *old_json = NULL, *new_json = NULL;

    va_list arg_ptr;
    va_start(arg_ptr, format);
    vasprintf(&str, format, arg_ptr);

    // save old json
    asprintf(&old_json, "%s", (*json == NULL ? "" : *json));

    // calloc new json memory
    new_json = (char *)calloc(strlen(old_json) + strlen(str) + 1, sizeof(char));

    strcat(new_json, old_json);
    strcat(new_json, str);

    if (*json) free(*json);
    *json = new_json;

    free(old_json);
    free(str);

    return 0;
}

int main(int argc, char *argv[])
{
    char *json = NULL;

    str_append(&json, "name: %d, %d, %d", 1, 2, 3);
    str_append(&json, "sex: %s", "male");
    str_append(&json, "end");
    str_append(&json, "");
    str_append(&json, "{\"ret\":true}");

    int i;
    for (i = 0; i < 10; i++) {
        str_append(&json, "id-%d", i);
    }

    printf("%s\n", json);

    if (json) free(json);

    return 0;
}
Wei
  • 9
  • 2
-1

I needed to append substrings to create an ssh command, I solved with sprintf (Visual Studio 2013)

char gStrSshCommand[SSH_COMMAND_MAX_LEN]; // declare ssh command string

strcpy(gStrSshCommand, ""); // empty string

void appendSshCommand(const char *substring) // append substring
{
  sprintf(gStrSshCommand, "%s %s", gStrSshCommand, substring);
}
Zac
  • 4,510
  • 3
  • 36
  • 44
-1
strcpy(str1+strlen(str1), str2);
dur
  • 15,689
  • 25
  • 79
  • 125
  • 1
    This fails because str1 must be unchanged (as per the question). – Michael Labbé May 24 '16 at 06:02
  • 4
    Could you explain how your answer addresses the problem(s) from the question? Code-only answers are not very useful, especially for further readers that stumble upon this post. Thanks! – Cristik May 24 '16 at 06:22
-3

man page of strcat says that arg1 and arg2 are appended to arg1.. and returns the pointer of s1. If you dont want disturb str1,str2 then you have write your own function.

char * my_strcat(const char * str1, const char * str2)
{
   char * ret = malloc(strlen(str1)+strlen(str2));

   if(ret!=NULL)
   {
     sprintf(ret, "%s%s", str1, str2);
     return ret;
   }
   return NULL;    
}

Hope this solves your purpose

eyalm
  • 3,366
  • 19
  • 21
maheshgupta024
  • 7,657
  • 3
  • 20
  • 18
  • 2
    I don't like the usage of printf for string concatenation. It can be easyly done using strcpy, strcat or even memcpy – eyalm May 05 '11 at 16:43
  • ya you are write.. but i thought to give u in a single statement.. or you can do strcpy(ret, str1) and then strcat(ret, str2). or as you said it will be faster with memcpy. – maheshgupta024 May 05 '11 at 16:52
  • 3
    How much space do you have go allocate for a copied string? Hint: It's not strlen(str). – Bo Persson May 05 '11 at 18:51
  • 1
    I thrown upon any code doing mallocs inside functions like that! – Ulterior Jun 12 '13 at 04:11
  • 2
    This code crashes because the malloc length does not allow for a null terminator. Also, multiple returns are redundant. – Michael Labbé May 24 '16 at 06:01
-4

You can try something like this:

strncpy(new_str, str1, strlen(str1));
strcat(new_str, str2);

More info on strncpy: http://www.cplusplus.com/reference/clibrary/cstring/strncpy/

Sitnik
  • 604
  • 5
  • 8
  • 2
    That's just horrible, there's no point in doing strlen(str1) here and using strncpy(), a plain strcpy() does the same thing. If you used sizeof new_str there would be a point. – unwind May 05 '11 at 16:40
  • 2
    I don't know if it's a typo or a gross misunderstanding of the `n` parameter of `strncpy`, but you need to provide the buffer size of `new_str`, not the length of `str1`. What happens here if `new_str` holds 5 characters but `str1` is 1000 characters long? – indiv May 05 '11 at 16:49
  • @indiv no misunderstanding. strncpy reference - num - Copies the first num characters of source to destination. Of course the length of the source buffer should be checked prior to this operation – Ulterior Jun 12 '13 at 04:11