60

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.

2
  • 5
    You're right, that's what it does. Commented May 5, 2011 at 16:35
  • 2
    For various reasons, you might want to keep track of the sizes of str1, str2, and new_str, and use strncat instead of just strcat). It'll help avoid some buffer overflow errors. Commented May 5, 2011 at 16:38

10 Answers 10

83

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.

Sign up to request clarification or add additional context in comments.

4 Comments

malloc can always return rubbish, and it does even on modern systems. calloc gives you zeroed memory.
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.
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).
Makes the memory look like an empty string. The memory returned by malloc, referred to by a void *, isn't anything -- by definition.
13

do the following:

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

3 Comments

With the caveat that new_str has to be initialized to an empty string.
This crashes when new_str can't hold the space or (*new_str) != 0
This keeps giving me "Segmentation fault"
8

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.

1 Comment

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.
2

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

Comments

0

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

char *new_str;
asprintf(&new_str,"%s%s",str1,str2);

1 Comment

This is inherently to specific to platforms where asnprintf is available though. It is not "standard".
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;
}

1 Comment

this would be very ineffective very fast solution
-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);
}

Comments

-1
strcpy(str1+strlen(str1), str2);

2 Comments

This fails because str1 must be unchanged (as per the question).
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!
-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

5 Comments

I don't like the usage of printf for string concatenation. It can be easyly done using strcpy, strcat or even memcpy
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.
How much space do you have go allocate for a copied string? Hint: It's not strlen(str).
I thrown upon any code doing mallocs inside functions like that!
This code crashes because the malloc length does not allow for a null terminator. Also, multiple returns are redundant.
-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/

3 Comments

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.
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 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.