Prepending to a string

sprintf() is generally not 'fast'. Since you know it's pre-pending memmove() twice would probably be preferable for speed.

If you're allocating the strings with malloc() originally you might consider using realloc() to resize the character arrays so they can contain the new string.

   char* p = malloc( size_of_first_string );
   ...
   p = realloc( p, size_of_first_string + size_of_prepended_string + 1 );
   memmove( p + size_of_prepended_string, p, size_of_first_string );
   memmove( p, prepended_string, size_of_prepended_string );

If you don't need the string to be stored in order, but only appear to be in order, then use a thing called a "rope." (It's made of lots of "string", see.)

I believe it's basically a vector (in C terms, an array) of struct { char *begin; char *end };

In C++ it implements all the std::string functions. In C you'd need to write (or get a library of) replacement functions for all the strxxx() functions.

What the "rope" would do to prepend a string to another string is simply insert a new begin,end pair pointing at the new piece of string. It might also have to copy the new piece of string, if it's a temporary pointer. Or it can just take ownership of the string if it's an allocated string.

A rope is very good for large strings. But anything under about 8 KB is faster to handle with memmove and memcpy.


Copying can hardly be avoided if you want it in the same memory chunk. If the allocated chunk is large enough you could use memmove to shift the original string by the length of what you want to prepend and then copy that one into the beginning, but I doubt this is less "clunky". It would however save you extra memory (again, granted that the original chunk has enough free space for them both).

Something like this:

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

void prepend(char* s, const char* t);

/* Prepends t into s. Assumes s has enough space allocated
** for the combined string.
*/
void prepend(char* s, const char* t)
{
    size_t len = strlen(t);
    memmove(s + len, s, strlen(s) + 1);
    memcpy(s, t, len);
}

int main()
{
    char* s = malloc(100);
    strcpy(s, "file");
    prepend(s, "dir/");

    printf("%s\n", s);
    return 0;
}