PHP like str_replace function in C

This post is part of a series of posts where I want to document a bunch of C functions I use for my projects that I have written, collected and modified over the past few years. One of the functions that I use regularly is a string replacement function like the str_replace in PHP. This function replaces all occurences of a particular substring with a replacement pattern. The code for this was borrowed from here. In the original code, a newly allocated string is returned after all the substrings are replaced. I have modified it so that the replacements are made in place.

/**
 *
 * str_replace.c implements a str_replace PHP like function
 * Copyright (C) 2010  chantra <chantra__A__debuntu__D__org>
 *
 */


#include "str_replace.h"


void
str_replace ( char **str, const char *substr, const char *replacement ){
  char *string =  *str;
  int findlen = strlen(substr), replacelen = strlen(replacement);
  int difflen = 0, totaldiff = 0;
  char *tok = NULL;
  char *newstr = NULL;
  char *oldstr = NULL;
  char *head = NULL;
  /* if either substr or replacement is NULL, duplicate string a let caller handle it */
  if(replacelen > findlen)
    difflen = replacelen - findlen;
  if ( substr == NULL || replacement == NULL ) return;
  newstr = strdup (string);
  head = newstr;
  while ( (tok = strstr ( head, substr ))){
    oldstr = newstr;
    newstr = malloc ( strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 1 );
    /*failed to alloc mem, free old string and return NULL */
    if ( newstr == NULL ){
      free (oldstr);
      exit(1);
    }
    memcpy ( newstr, oldstr, tok - oldstr );
    memcpy ( newstr + (tok - oldstr), replacement, strlen ( replacement ) );
    memcpy ( newstr + (tok - oldstr) + strlen( replacement ), tok + strlen ( substr ), strlen ( oldstr ) - strlen ( substr ) - ( tok - oldstr ) );
    memset ( newstr + strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) , 0, 1 );
    /* move back head right after the last replacement */
    head = newstr + (tok - oldstr) + strlen( replacement );
    free (oldstr);
    totaldiff += difflen;
  }
  free(*str);
  *str = (char *) calloc(sizeof(char), (strlen(newstr) + 1));
  strcpy(*str, newstr);
  free(newstr);
  return;
}

int main(void) {
  char *string;
  string = (char *) malloc(50*sizeof(char));
  sprintf(string, "I'm a bad bad boy");
  printf("Original String - %s\n'bad' will be replaced with 'good'\n", string);
  str_replace(&string, "bad", "good");
  printf("Modified String - %s\n", string);
  free(string);
  return 0;
}
#ifndef _STR_REPLACE_H
#define _STR_REPLACE_H

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

void str_replace ( char **string, const char *substr, const char *replacement );

#endif /* _STR_REPLACE_H */

Copy the above code into str_replace.c and str_replace.h and compile it and execute it.

@~ $  make str_replace
@~ $  ./str_replace 
Original String - I'm a bad bad boy
'bad' will be replaced with 'good'
Modified String - I'm a good good boy

1 comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.