6

Ok, so I have a char stringA and char stringB, and I want to be able to insert stringB into stringA at point x.

char *stringA = "abcdef";
char *stringB = "123";

with a product of "ab123cdef"

does anyone know how to do this? Thanks in advance

6
  • Also, you tagged this C++. If it's C++ and it's not homework, why not just use std::string? Commented Jan 6, 2010 at 20:20
  • I know how to do it with a std::string, and ya it is homework Commented Jan 6, 2010 at 20:26
  • 1
    If this is homework (or even if it weren't), I would suggest that you edit your post to include what you have already tried, and where you've gotten stuck. As it is, you are simply asking someone else to do your homework for you. Commented Jan 6, 2010 at 20:30
  • C or C++? The right (well, preferred) answer will be different for each. Commented Jan 6, 2010 at 20:34
  • 7
    @mcl: if we let people do these things for themselves, they will become good programmers. We don't need more competition. Commented Jan 6, 2010 at 20:43

6 Answers 6

16
char * strA = "Blahblahblah", * strB = "123", strC[50];
int x = 4;
strncpy(strC, strA, x);
strC[x] = '\0';
strcat(strC, strB);
strcat(strC, strA + x);
printf("%s\n", strC);

Explanation:

  1. You declare the two strings you will be joining, plus a third string into which you will put them.
  2. You declare an integer to tell the program after how many characters you wish to insert the second string into the first.
  3. The strncpy function copies the first x characters into strC. You have to add the null ('\0') character at the end, otherwise you'll probably get rubbish.
  4. Strcat to copy the second string.
  5. Another strcat to copy the remaining part of the first string (strA + x).

Hope that helps.

Remark: remember to make strC long enough to contain both strA and strC, otherwise you'll produce a segmentation fault. You may do this by declaring the string as an array, like in my example.

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

6 Comments

ya i just used: char* strC = (char*)malloc(strlen(strA) + strlen(strB_); perfect answer thank you!
@Sj, don't forget the null char!
@Sj: it should be char * strC = malloc(strlen(strA)+strlen(strB)+1). You forgot about the additional character for the '\0'. It might seem to work, but you have a chance of overwriting a byte of something that's not your string. I'm not sure gdb will catch this, but electric fence will complain.
I would think this to be the best solution because it does not malloc memory. If you malloc memory then you must free it or you have created a memory leak. And if you do free the memory malloc'd then either, you must use it in the immediate scope in which it was created, or send the pointer elsewhere where it must be tracked so it can later be freed. If you create a oversized array then the OS will deal with freeing the memory.
Using strcpy and strcat in examples is a bad idea. It propagates the unsafe use that leads to many critical vulnarabilities, around for decades now. Please remember to use strlcpy, and related members of the "l" sort!
|
9

stringA and stringB are both pointers - they contain the starting address for a blob of memory. The memory they are pointing to contain continuous strings of characters: "abcdef" and "123" respectively. Since strings are contiguous blocks memory (meaning that the memory location of a given character is one byte after the previous) you can't insert more characters into the middle of a string without first moving some characters. In your case you can't even really do this, since the amount of memory allocated for each string is exactly large enough to hold JUST that string (ignoring padding).

What you are going to have to do is copy the strings to another block of memory, one that you have allocated for that purpose, and copy them so that the second string starts x characters into the first string.

Several other SO users have posted code-solutions but I think you should try and find the exact solution on your own (and hopefully my high-level explanation of what's going on will help).

Comments

3

Here a more general solution.

Note that destination must have enough space in memory to add seed (e.g. an heap-allocated array of size grater than strlen(seed)+strlen(destination) ). So, concerning the question, you have to create a larger array.

/* 
    destination: a NULL terminated string
    pos: where insert seed
    seed: a NULL terminated string
*/
void insertString(char* destination, int pos, char* seed)
{
    char * strC;

    strC = (char*)malloc(strlen(destination)+strlen(seed)+1);
    strncpy(strC,destination,pos);
    strC[pos] = '\0';
    strcat(strC,seed);
    strcat(strC,destination+pos);
    strcpy(destination,strC);
    free(strC);
}

Comments

2
int insert_pos = 5;
int product_length = strlen(stringA) + strlen(stringB) + 1;
char* product = (char*)malloc(product_length);
strncpy(product, stringA, insert_pos);
product[insert_pos] = '\0';
strcat(product, stringB);
strcat(product, stringA + insert_pos);
...
free(product);

1 Comment

If you want to write safe software, avoid strcpy and such, and instead use the "l" variants where you pass the size of the modified string, making sure you don't get accidendal overflows that can crash your app and make it vulnerable to attacks. e.g: strlcpy (product, ..., sizeof(product). If you find that cumbersome, make yourself a Macro for it: #define STRCPY(a,b) strlcpy (a, b, sizeof(a)). Same for strcat etc.!
0

There are plenty of answers here. However, most do rely on strcat() instead of using efficiently the length computed for the allocation, none is secure, and none offers a solution for in-place insertion.

Case 1: you want to allocate a new string

Just copy the different string components to their target address, avoiding to iterate over them with strcat(), considering that computing once their length is sufficient. Keep in mind that malloc() might return NULL:

char* strmake_insert (const char *str, size_t pos, const char *insertstr) 
{
    size_t sl = strlen(str), il = strlen(insertstr);
    
    char *newstr=malloc(sl+il+1);
    if (newstr) {
        memcpy (newstr, str, pos);
        memcpy (newstr+pos, insertstr, il);
        memcpy (newstr+pos+il, str+pos, sl-pos);   
    }
    return newstr; 
}  

Example of use:

char *s = strmake_insert ("abcdef", 3, "123"); printf ("New string: %s\n", s); free(s);

I leave as an exercise the strengthening of this version into a secure one.

Case 2: you want to insert in-place in the original string

We'll assume here that there is enough space in the buffer allocated for the original string. Use memcpy() that can deal with overlapping arrays, whereas strcpy() is not guaranteed to do this properly. This code assumes however that the string to insert does not overlap with the original string:

void strinsert (char *str, size_t pos, const char *insertstr) 
{
    char *where =str+pos; 
    memcpy(where+strlen(insertstr), where, strlen(where)+1);
    memcpy(where, insertstr, strlen(insertstr));
}  

Example of use:

char mystring[100]; 
strcpy (mystring, "abcdef");
strinsert (mystring, 3, "123"); 
printf ("Altered string: %s\n", mystring); 

This is however an insecure version, as the check for sufficient space must be performed elsewhere and buffer overflows are quite common unfortunately.

Case 2: same but secured version

The following code does not use strnlen_s() and memcpy_s() which would additionally check for border cases with NULL pointers or zero length, as these functions are not available on a number of implementations. But this one already protects against common buffer size problems:

int strinsert_s (char *str, size_t pos, size_t strsz, 
                       const char *insertstr, size_t inssz) 
{
    char *where =str+pos; 
    size_t wheresz = strsz-pos;       // maximum size at insert point 
    size_t insertlen = strnlen(insertstr,inssz);
    if (pos>=strsz || pos>=strlen(str) ) // if insert pos invalid 
        return EOVERFLOW; 
    size_t wl = strnlen(where,wheresz); 
    if (wl<wheresz) // if null terminated take the trailing '\0' 
       wl++;
    if (wheresz<=insertlen || wheresz-insertlen<=wl) // if  insert string too large
        return EOVERFLOW;    
    memcpy (where+insertlen, where, wl);
    memcpy (where, insertstr, insertlen);
    return 0;  
}  

Example of use:

char mystring[100]; 
strcpy (mystring, "abcdef");
errno_t err = strinsert_s (mystring, 3, sizeof(mystring), "123",4); 
if (err) 
    printf ("Error %d\n", err); 
else printf ("Altered string: %s\n", mystring); 

Example of buffer overflow prevented:

char mystring[9]; // the trailing '\0' will go out of buffer - nasty! 
strcpy (mystring, "abcdef");
int err = strinsert_s (mystring, 3, sizeof(mystring), "123",4); 
if (err) 
    printf ("Error %d\n", err); 
else printf ("Altered string: %s\n", mystring); 

Comments

-1
char *strInsert(char *str1, const char *str2, int pos) {
    size_t l1 = strlen(str1);
    size_t l2 = strlen(str2);

    if (pos <  0) pos = 0;
    if (pos > l1) pos = l1;

    char *p  = str1 + pos;
    memmove(p + l2, p, l1 - pos);
    memcpy (p, str2,  l2);
    return str1;
}

Comments

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.