Home > Back-end >  Insert a string inside of another string (without an intermediate string)
Insert a string inside of another string (without an intermediate string)

Time:12-02

I came across this question and it asks if it's possible to write the function

void insert(char* M, char* T, int i)

that inserts the string T inside M starting from the index i, without using an intermediate string... I tried to use realloc but I think there's a problem when the original string M is a lot smaller than the result, my theory is that realloc changes the address of the string to be able to represent the new string.

For example: M="Wg" T="ron" and i=1; the result should be M="Wrong".

I'm using the following code:

void insert(char* M,char* T,int i)
{
    int l;
    l=strlen(M);
    M=realloc(M,l strlen(T) 1);

    for(int j = l-1; j >= i; j--)
    {
        M[j strlen(T)]=M[j];
    }

    for(int j = 0;j < strlen(T); j  )
    {
        M[i j]=T[j];
    }

    M[l strlen(T)]='\0'; //from what i've tested the string M is correct.
}

and using this declaration:

    char *s=malloc(3);
    char *c=malloc(18);
    strcpy(s,"as");
    strcpy(c,"bcdefghijklmnopqr");
    insert(s,c,1); //this example does not work on my machine.

I hope this clarifies the question.

So is there a way to do it?

CodePudding user response:

Example of a possible implementation using memmove. Explanations are in the comments

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

void insertString(char* M, const char* T, size_t index)
{
    // ASSUMES there's enough space in M for this operation
    // get the original lengths of each string
    size_t Mlen = strlen(M);
    size_t Tlen = strlen(T);

    if (index < Mlen)
    {
        // M index Tlen is the destination position where the remaining characters in M will start
        // M index is the index where T will be inserted
        // Mlen-index is the remaining number of characters in M that need to move
        memmove(M index Tlen, M index, Mlen-index);
        // copy the T string to the space we just created
        memcpy(M index, T, Tlen);
        // NUL terminate the new string
        M[Mlen   Tlen] = '\0';
    }
    else
    {
        // simply strcat if the index falls outside the range of M
        strcat(M, T);
    }
}

If you're not allowed to use memmove or memcpy, it's simple enough to roll your own.

Demo

CodePudding user response:

[This isn't really an answer; it's a clarification that's too complicated for a comment.]

If you can assume that the caller looks like

char string[6] = "Wg";
insert(string, "ron", 1);

(or with the string array having any size greater than 5), then you can write insert() easily.

If you can assume that the caller looks like

char *string = malloc(3);
strcpy(string, "Wg");
insert(string, "ron", 1);

then you can almost write insert() using realloc to make the string larger, except you have no way to return the possibly-new (that is, possibly moved) value of string.

If the caller might look like

char *string = "Wg";
insert(string, "ron", 1);

or even

char *string = "Wg\0\0\0";
insert(string, "ron", 1);

than you definitely cannot write insert(), because you cannot assume that the pointed-to string is writable (and on many platforms it will not be).

So, in general, the answer is: "No". You cannot write a general-purpose version of insert() that will work under all circumstances.

Note, too, that if you were to assume that the string were in malloc'ed memory and that you could use realloc (as in my second example), that code would not work for strings that were not malloc'ed (that is, it would not work for callers like my first example), and it would have no portable way of knowing, based on the pointer passed to it, whether it would be abe to safely use realloc or not.

  • Related