[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 12828
  • Last Modified:

How do I remove a substring from a string in C

This may seem very simple. Undoubtably I am missing some small component of understanding that would make it all clear. One of the difficulties I am having with C is how to elegantly manipulate strings. For instance how can I remove a substring from a string efficiently? I think my problem conceptually is that it would seem that I should use strstr somehow but I can't figure out how to make proper use of the returned pointer.

Example:
char* strBefore = "This is a string remove to test";
char* strToRemove = "remove";
char* strAfter = "This is a string to test";

Below is my attempt which is not working:
Thanks,
ibanja

#include<iostream>
#include<string.h>

using std::cout;
using std::cin;

char *strstr_rem(char *string, char *substring);

char *strBefore = "This is a sample string remove to test";
char *strToRemove = "remove";

int main()
{

  char* strAfter = strstr_rem(strBefore, strToRemove);
  cout << strAfter;

}


char *strstr_rem(char *string, char *substring)
{
  char* strStart =  strstr(string, substring);
  size_t lenSubStr = strlen(substring);
  char* strNew[strlen(string) - lenSubStr];

  int i = 0;
  while (string[i])
    {
      if (&strStart == &string[i])
      i+=lenSubStr;
      else
      strNew[i] = string[i++];
    }

  return strNew;
}
0
ibanja
Asked:
ibanja
  • 18
  • 11
  • 2
  • +2
3 Solutions
 
PaulCaswellCommented:
Hi ibanja,

Here's a routine I use to replace a part of a string with another. Pass it a pointer to where you want the replace to happen, probably the result of your call to strstr. I am sure you could either use it as-is or adjust it to fit your needs:

// Replace a section of a string with another.
size_t ReplaceSection ( char * string, size_t length, char * replace )
{
    size_t repLength = (replace == NULL ? 0: strlen(replace));

    // Something to move?
    if ( length != repLength )
    {
        // Make room.
        memmove ( &string[repLength],&string[length], strlen(&string[length]) + 1 );
    }
    // Is there something to replace.
    if ( repLength > 0 )
    {
        // Copy it in.
        memcpy ( string, replace, repLength );
    }
    return repLength;
}

Paul
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi ibanja,

String manipulation in C is pretty easy, once you get the hang of it.  But there are some techniques that you'll need to learn.

To remove a substring from with in a string, you need to do two things.  Find the substring, move the substring past the search item UP so that it covers the search string.

  Consider this string.    THIS IS A FINE EXAMPLE.

Now we want to remove "FINE" from the string.  At this point the only thing that we know is the starting address of the string and the starting address of the substring.

  char *strBefore = "THIS IS A FINE EXAMPLE";
  char *strToRemove = "FINE";
  char *strLocation;
  char strAfter[100];

Lets start by copying the entire source string to the target string.

  strcpy (strAfter, strBefore);

Then we need to find out if the substring is in the string.  strstr() works fine.

  strLocation = strstr (strAfter, strToRemove);

If the return value is NULL, the string wasn't found so there is nothing to do.  However, if the return value is NOT NULL then we simply need to move a few characters around.

  if (strLocation != NULL)
    strcpy (strlocation, strlocation + strlen (strToRemove);

What that does, is copy the string starting at the first character PAST what we found to the location where the substring was found.  In this example, " EXAMPLE" is copied over "FILE EXAMPLE" leaving us with:

  THIS IS A  EXAMPLE.

Note that there are two spaces between "A" and "EXAMPLE".  We should probably clean that up, too.  But the base problem is solved.  :)

Good Luck!
Kent
0
 
ibanjaAuthor Commented:
Hi Kent,

At a quick glance your answer seems to be what I'm looking for.  I am going to spend some time with it and digest it a bit and I will get back.  

An aside - I know there was another answer by someone else.  I checked about 30 minutes ago and read it then went and ran an erand.  When I got back it was gone.  Earlier today I also couldn't find a solved post I made, about namespaces, from about a month ago.  I am wondering if there is some kind of issue going on with this site (or is it me).  

Anyway,
Thanks,
ibanja
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
ibanjaAuthor Commented:
OK, Now I see the Comment from PaulCaswell is back. Hmm. Nevermind...
0
 
PaulCaswellCommented:
Hi ibanja,

>>... another answer ...

That was me! Its back now! We have rules about homework here and when Kent posted his comment I suddenly thought this may be one of those so I deleted it while I checked. I dont think it is so  put it back but if this is homework, please make sure you learn from the code rather than just copying it.

Sorry.

Paul
0
 
PaulCaswellCommented:
ibanja,

Is this the question you lost?

http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_21782724.html

If you click on your name in any question it takes you to your question history. I found it there.

The database search system takes several weeks to update completely so for fairly recent questions, this is the way to go:

http://www.experts-exchange.com/M_3529116.html

Paul
0
 
ibanjaAuthor Commented:
Hi Kent,

Yes that's the link - thank you.

And no worry - I am 45 years old and done with homework :) I use this forum only after much thought and investigation, although it may not seem as such to those who are well versed in the subjects. I usually find that I am missing one little conceptual piece of the puzzle and the experts can bring light to my misconceptions.

Thanks,
ibanja
0
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi ibanja,

45?  Still a puppy, huh?   :~}


Kent
0
 
PaulCaswellCommented:
Hi Kdo,

These young-uns ... huh ... what is the world coming to :-)

Hi ibana,

Welcome to the old-folks home! :-) Nice to meet someone without a single exam looming!

Paul
0
 
ibanjaAuthor Commented:
Glad to see a sense of humor doesn't diminish with age.  

Oops, better watch it. I may not get any more help :o)

ibanja
0
 
ibanjaAuthor Commented:
Kdo,

I have been trying two versions of functions using the concept from your explanation.  This function (code below) is meant to change the actual string passed through it as opposed to another function I'm making which returns a new, different changed string.  The problem I'm having is that it is getting a "Segmentation fault" error.  Running in the debugger shows that right after stepping past the line:
 char *strLocation =  strstr(string, substring);
the value of string changes from "THIS IS A FINE EXAMPLE" to  "FINE EXAMPLE".
 
GDB Output:
(gdb) print string
$10 = 0x80485be "THIS IS A FINE EXAMPLE"
(gdb) s
(gdb) print string
$11 = 0x80485c8 "FINE EXAMPLE"

Why would the string pointer be moved like this? I thought strstr was just assigning the substring location address to strLocation.  This must be why you copied source to target at the outset, but I don't see why this result. Any insights much appreciated. BTW - it seg faults in strcpy with string equaling "EXAMPLE".

Thanks,
ibanja

Code:
#include<string.h>

void strstr_rem(char *string, char *substring);

char *strToChange = "THIS IS A FINE EXAMPLE";
char *strToRemove = "FINE ";

int main()
{

  strstr_rem(strToChange, strToRemove);
  printf("%s\n",strToChange);

}

void strstr_rem(char *string, char *substring)
{
  char *strLocation =  strstr(string, substring);

  if(strLocation != NULL)
    strcpy(strLocation,strLocation + strlen(substring));
}
0
 
sunnycoderCommented:
Hi ibanja,

>char *strToChange = "THIS IS A FINE EXAMPLE";
>char *strToRemove = "FINE ";

Change these to

char strToChange[] = "THIS IS A FINE EXAMPLE";
char strToRemove[] = "FINE ";

In your current form, the strings would be kept in read only data area - they are string literals. When you try to write on them, you get a seg fault.

Keep them on stack as shown above and things should work fine.

Cheers!
sunnycoder
0
 
sunnycoderCommented:
Also I am not sure how good an idea is it to use

>strcpy(strLocation,strLocation + strlen(substring));

strlen does not guarantee that it would copy from start to finish char by char. It can copy from anywhere in any amounts as long as it guarantees correct end behavior - for two no overlapping strings.

For overlapping strings, it might be better use a function which guarantees correct handling in case of overlap - such as memmove - which Paul used in his initial example.

Cheers!
sunnycoder
0
 
ibanjaAuthor Commented:
Thanks sunnycoder,

That did it.  I'll have to remember that.

ibanja

0
 
ibanjaAuthor Commented:
sunnycoder,

I didn't initially understand Paul's code - but after reading the memmove man page and looking at a couple of web examples I think you are right.  I'll have to spend some more time with it tomorrow.

Thanks,
ibanja
0
 
ibanjaAuthor Commented:
Thanks to everyone for the help. I've actually learned a whole lot from all three of your posts so I thought I would split up the points. I hope this works for everyone. I don't think I've ever had to split the points so widely before. Since Kdo's example and explanation gave me the most clarity, conceptually, on how to manipulate c-style strings I figured on giving him the "accepted answer".  Paul's example was very helpful as an alternative to the examples on the web and studying it enabled me to get a grasp of memmove. sunnycoder pulled it all together for me pointing out the value of Paul's use of memmove, not to mention straightening me out on string literals being kept in read only data area.  

Thanks,
ibanja

For anyone else seeking answers and reading this in the future. This is what I came up with using Paul's idea (memmove).  I haven't made it into a function yet.:

#include<string.h>

char strToChange[] = "THIS IS A FINE EXAMPLE";
char strToRemove[] = "FINE ";

int main()
{

  size_t keepUpTo = strstr(strToChange, strToRemove) - strToChange;
  size_t chLen = strlen(strToChange);
  size_t rmLen = strlen(strToRemove);
  size_t replaceUntil = (chLen - keepUpTo - rmLen) +1;

  memmove (strToChange+keepUpTo, strToChange+(keepUpTo+rmLen), replaceUntil );
  printf("%d\n", keepUpTo);
  printf("%d\n", chLen);
  printf("%d\n", rmLen);
  printf("%d\n", replaceUntil);
  printf("%s\n", strToChange);
}

Output:$ ./mem_move
10
22
5
8
THIS IS A EXAMPLE

*** Next ***
This is the version I came up with from Kdo using strspy:
#include<string.h>

char * strstr_rem(char *string, char *substring);

char strToChange[] = "THIS IS A FINE EXAMPLE";
char strToRemove[] = "FINE ";

int main()
{

  strstr_rem(&strToChange, strToRemove);
  printf("%s\n",strToChange);

}

char * strstr_rem(char *string, char *substring)
{
  char *strLocation =  strstr(string, substring);

  if(strLocation != NULL)
    strcpy(strLocation,strLocation + strlen(substring));

  return strLocation;
}

Output:$ ./strRem
THIS IS A EXAMPLE

0
 
ibanjaAuthor Commented:
Here is the function version of using memmove for those who might benefit from it.  
If anyone sees any problems with this feel free to let me know.

Thanks.

// str_rem removes substring from string.
#include<string.h>

char strToChange[] = "THIS IS A FINE EXAMPLE";
char strToRemove[] = "FINE ";

void str_rem(char *string, char *substring);

int main()
{
  str_rem (strToChange, strToRemove);
  printf("%s\n", strToChange);
}

// str_rem removes substring from string.
void str_rem(char *string, char *substring)
{
  size_t keepUpTo = strstr(string, substring) - string;
  size_t chLen = strlen(string);
  size_t rmLen = strlen(substring);
  size_t replaceUntil = (chLen - keepUpTo - rmLen) +1;

  memmove (string+keepUpTo, string+(keepUpTo+rmLen), replaceUntil );
}

Output:$ ./str_rem
THIS IS A EXAMPLE
0
 
PaulCaswellCommented:
Good work ibanja.

There's one potential issue you may find it interesting to avoid.

What happens if the substring isn't in the string?

Paul
0
 
ibanjaAuthor Commented:
Funny you should mention that Paul. :)

I just seg faulted because of this very reason. Below is what I rewrote.  Initially I just added an "if" line that said
if(strstr(string, substring) != NULL)
{
size_t keepUpTo = strstr(string, substring) - string;
code ...

but it seemed a waste to call strstr twice on the same two strings so I changed it to this:

void str_rem(char *string, char *substring)
{
  char* loc = strstr(string, substring);
  if( loc != NULL)
    {
      size_t keepUpTo = loc - string;
      size_t chLen = strlen(string);
      size_t rmLen = strlen(substring);
      size_t replaceUntil = (chLen - keepUpTo - rmLen) +1;
     
      memmove (string+keepUpTo, string+(keepUpTo+rmLen), replaceUntil );
    }
}


I'm slowly getting it:)  Thanks again for the helpful input.
ibanja
0
 
PaulCaswellCommented:
Hi ibanja,

Good work! You got it! You've now got something that will always work (I think). Now we can look at making sure we arent doing more than we need.

1. What is the difference between 'string+keepUpTo' and 'loc'?
2. 'string+(keepUpTo+rmLen)' is obviously the same as '(string+keepUpTo)+rmLen'. How can you make use of that once you have considered 1. above?
3. (I havent worked out the answer to this in this case) What happens if 'string' or 'substring' are empty, or even both?

If you get bored with all this just say so! I just keep going back to your original 'elegantly manipulate strings' phrase. It can be done and it can be elegant but it's not easy without some thought beyond getting it right.

Paul
0
 
ibanjaAuthor Commented:
Hi Paul,

No, not bored at all. I prefer the "right way" of doing things and enjoy it.  Thanks!

I have changed the function a bit. It seems to handle empty strings gracefully. I also added a return value (char * loc) whereby if there is no more string to remove it returns NULL.  This allows a while loop until all strings are removed. I think I see now why you've made your function, ReplaceSection, so you can pass a pointer/position to the specific string to be removed/replaced.  That way one specific string can be removed if there is more then one match.

I also wrote a str_rep function to replace strings.  I can see that needs reworking too :).

Here is my latest version of str_rem with output. I believe that's as lean as it can go:

#include<string.h>

char strToChange1[] = "THIS IS A FINE EXAMPLE";
char strToChange2[] = "THIS IS A FIINE EXAMPLE";
char strToChange3[] = "THIS IS A FINE FINE FINE EXAMPLE";
char strToRemove[] = "FINE ";
char empty1[] = "";
char empty2[] = "";

char* str_rem(char *string, char *substring);

int main()
{
  str_rem (strToChange1, strToRemove);
  str_rem (strToChange2, strToRemove);
  str_rem (empty1, empty2);
  str_rem (empty2, "ffff");
  printf("%s\n", strToChange1);
  printf("%s\n", strToChange2);
  printf("%s", empty1);   // leave off "\n" to see empty.
  printf("%s\n", empty2);

  while (str_rem(strToChange3, strToRemove))
    ;
    printf("%s\n", strToChange3);
}

// str_rem removes substring from string.
char* str_rem(char *string, char *substring)
{
  char* loc = strstr(string, substring);
  if( loc != NULL)
    {
      size_t keepUpTo = loc - string;
      size_t chLen = strlen(string);
      size_t rmLen = strlen(substring);
      size_t replaceUntil = (chLen - keepUpTo - rmLen) +1;
     
      memmove (loc, loc+rmLen, replaceUntil );
    }
  return loc;
}

Output:$ ./str_rem
THIS IS A EXAMPLE
THIS IS A FIINE EXAMPLE

THIS IS A EXAMPLE


Thanks,
ibanja
0
 
PaulCaswellCommented:
Hi ibanja,

I think you are nearly there. You should, however, be able to do this without 'strlen(string)'. Consider this. Once you know that the substring is in the string and you know the length of the substring, how much to move is the ramainder of the string beyond the substring plus one. That's what I am doing with 'strlen(&string[length]) + 1' in

        memmove ( &string[repLength],&string[length], strlen(&string[length]) + 1 );

This is only a tiny improvement, it takes longer to find the length of a longer string than a shorter one but only slightly.

The final optimisation would be to realise that all those local variable need to be stored on the stack and retrieved from it and that adds a few unnecessary clock cycles. Again notice that my code uses only one stack variable because otherwise its value would need to be calculated twice which would have a much higher cost.

Paul
0
 
cwwkieCommented:
I think there is something more to improve besides the speed optimisations.

>>   // str_rem removes substring from string.
>>   char* str_rem(char *string, char *substring)

You have changed the function to return NULL if no replacement has been made.
You should add that to the comment before the function definition. If someone else wants to use your function, or finds a bug in it, it is important to know what exactly the function does (or should do).
0
 
ibanjaAuthor Commented:
Hi Paul,

Phew, I don't know why I couldn't see that for a while.  But now that I have it, it seems obvious. One thing I'm not sure about is do I assign a pointer for (loc + rmLen) or calculate it twice?

      // Calculate twice:
      // Or do I do this:
      //      char * loc_rmLen = loc + rmLen;
      //      memmove (loc, loc_rmLen, strlen(loc_rmLen) +1 );

I am thinking now that the pointer would be better.

Thanks much for the help with this. I learned a lot. I'm now in the process of fixing the str_rep function that replaces a string. Since paring this function down I see a lot of improvements to be made on str_rep.

ibanja

Here is the improved str_rem:

// str_rem removes substring from string.
// returns NULL if no substring to remove. // Thanks cwwkie
char* str_rem(char *string, char *substring)
{
  char* loc = strstr(string, substring);
  if( loc != NULL)
    {
      size_t rmLen = strlen(substring);

      memmove (loc, loc + rmLen, strlen(loc + rmLen) +1 );
    }
  return loc;
}
0
 
ibanjaAuthor Commented:
Hi Paul,

Phew, I don't know why I couldn't see that for a while.  But now that I have it, it makes sense. One thing I'm not sure about is do I assign a pointer for (loc + rmLen) or calculate it twice?

      // Calculate twice:
      // Or do I do this:
      //      char * loc_rmLen = loc + rmLen;
      //      memmove (loc, loc_rmLen, strlen(loc_rmLen) +1 );

I am thinking now that the pointer would be better.

Thanks much for the help with this. I learned a lot. I'm now in the process of fixing the str_rep function (again) that replaces a string. Since paring this function down I see a lot of improvements to be made on str_rep.

ibanja

Here is the improved str_rem:

// str_rem removes substring from string.
// returns NULL if no substring to remove. // Thanks cwwkie
char* str_rem(char *string, char *substring)
{
  char* loc = strstr(string, substring);
  if( loc != NULL)
    {
      size_t rmLen = strlen(substring);

      memmove (loc, loc + rmLen, strlen(loc + rmLen) +1 );
    }
  return loc;
}
0
 
ibanjaAuthor Commented:
Just thought I'd post the str_rep for good measure.

// str_rep replaces substring within a string.
// returns NULL if no substring to replace.
char * str_rep(char *string, char *strToRep, char *strReplacement)
{
  char* loc = strstr(string, strToRep);
  if( loc != NULL)
    {
      size_t toRepLen = strlen(strToRep);
      size_t repLen = strlen(strReplacement);
      memmove (loc + repLen , loc + toRepLen, strlen(loc + toRepLen)  +1);
      memmove (loc , strReplacement, strlen(strReplacement));
      }
  return loc;
}
0
 
PaulCaswellCommented:
Hi ibanja,

Looks like you're getting the hang of it! :-)

The final exercise is to quickly run through all the possible problems and decide a) whether to deal with it at all or b) make sure you have dealt with it.

In case a) it is a good idea to document it too.

char* str_rem(char *string, char *substring)
{
  char* loc = strstr(string, substring); // Would crash if either string or substring are NULL. My opinion is type 'a'.
  if( loc != NULL)
    {
      size_t rmLen = strlen(substring);

      memmove (loc, loc + rmLen, strlen(loc + rmLen) +1 );
     // Would crash if loc or loc + rmLen were NULL. Impossible.
     // Would crash if loc + rmLen pointed off the end of string. Impossible.
     // Would crash if strlen(loc + rmLen) +1 was too long to fit in string. Impossible.
    }
  return loc;
}

Conclusion: Good healthy code!

Have a go at the same analysis of str_rep. I think its clean too,

One final point:

      memmove (loc , strReplacement, strlen(strReplacement));

can be:

      memmove (loc , strReplacement, repLen);

but I expect you've already seen that or would have done soon enough.

Paul
0
 
PaulCaswellCommented:
One last thought, on the subject of crash-testing.

char test[] = "A Word is a Word is a Word";

// Hope to remove the first 'Word is a Word' in an obscure way ;-)
str_rem(test, &test[12]);

I'm not saying you should handle this, or document it for that matter. Its just interesting that often, however bomb-proof you make your code, there's always some way of making it go bang, or does it?

One final excercise if you're still up to it.

Notice how much code the two functions share. Why not allow 'str_rep(string, rep, NULL)' or 'str_rep(string, rep, "")' to be equivalent to 'str_rem (string, rep)'. I.e. treat an empty or null replacement string as a removal of the 'rep' string. Try not to look at my code above while you are doing it :-)

Paul
0
 
ibanjaAuthor Commented:
Hi Paul,

Haven't been able to look at this in depth until today.

>// Hope to remove the first 'Word is a Word' in an obscure way ;-)
>str_rem(test, &test[12]);

Interesting concept. I was playing with it and found it could also be used to remove the end of string by passing &test[12] to both args. Here are the results.

Code:
   printf("%s\n",test);  
   str_rem(test, &test[12]);
   printf("[%s]\n", test);

Output:
$ ./str_rem
A Word is a Word is a Word
[A  is a Word]

Code:
   printf("%s\n",test);  
   str_rem(&test[12], &test[12]);
   printf("[%s]\n", test);

Output:
$ ./str_rem
A Word is a Word is a Word
[A Word is a ]


Surprisingly, at least to me, the str_rep segfaults after printing "Very NICE Very NICE Very NICE ... Very NICE THIS IS A FINE FINE FINE EXAMPLE" when passed a NULL for the strToReplace (strToRep).

There are hundreds of "very NICE" printed and then "THIS IS A FINE FINE FINE EXAMPLE" then a Segmentation fault.

Code:
char strToChange3[] = "THIS IS A FINE FINE FINE EXAMPLE";
char strToReplace[] = "\0";
char strReplacement[] = "Very NICE ";

int main()
{
  while( str_rep (strToChange3, strToReplace, strReplacement) )
    printf("%s\n", strToChange3);
}



I haven't figured out what's wrong yet but I'm thinking a clue would be that this:

char strToChange1[] = "THIS IS A FINE EXAMPLE";

int main()
{
  str_rep (strToChange1, strToReplace, strReplacement);
  printf("%s\n", strToChange1);
}

produces this output:
$ ./str_rep
Very NICE THIS IS A FINE EXAMPLE

Still working on it. It's getting late. I'll fire up the debugger tomorrow.

Thanks,
ibanja
0
 
ibanjaAuthor Commented:
I should show the other variables:

char strToChange1[] = "THIS IS A FINE EXAMPLE";
char strToReplace[] = "\0";
char strReplacement[] = "Very NICE ";

int main()
{
  str_rep (strToChange1, strToReplace, strReplacement);
  printf("%s\n", strToChange1);
}
0
 
PaulCaswellCommented:
Hi ibanja,

char strToChange1[] = "THIS IS A FINE EXAMPLE";
char strToReplace[] = "\0";
char strReplacement[] = "Very NICE ";

These allocate exactly (and only) the right amount of space to store the strings. If you then increase the string length of strToChange it will begin to overwrite the others. For safety, you'd be better to use something like:

char strToChange1[100] = "THIS IS A FINE EXAMPLE";
char strToReplace[] = "\0";
char strReplacement[] = "Very NICE ";

Have Fun!

Paul
0
 
ibanjaAuthor Commented:
Hi Paul,

Learned a lot here.

I tried:
char strToChange1[100] = "THIS IS A FINE EXAMPLE";
but it turns out it was the while loop expecting an eventual NULL that it never got that caused the error.  What was happening was the
strstr(string, "");
returned a pointer to the beginning of string, so the function continued and prepended the strReplacement onto string and then the while loop looped through and did it again, and again and again...

I fixed the segfault by adding a check for strToReplace.  If it doesn't exist then the function returns NULL. It was a big decision between leaving it the way it was or removing the prepend feature.

The while loop:
 while( str_rep (strToChange, strToReplace, strReplacement) )
is useful for replacing multiple occurrences of the strToReplace so I decided it would be better to make its implementation clean.

Code(the documentation is improving :) ):
// str_rep replaces the first occurrence of a substring within a string.
// Returns NULL if no substring found to replace.
// Returns NULL if strToReplace is blank.
// Removes strToReplace if strReplacement is NULL or "".
char * str_rep(char *string, char *strToReplace, char *strReplacement)
{
  char* loc = strstr(string, strToReplace);
  if( (loc != NULL ) ) // Asking if strToReplace was found.
    {
      size_t toRepLen = strlen(strToReplace);
      if(toRepLen != 0)  // Make sure there is something to replace.
            {
        size_t repLen = strlen(strReplacement);
        if( repLen != 0) // If there is no replacement then just remove.
          {
            memmove (loc + repLen , loc + toRepLen, strlen(loc + toRepLen)  +1);
            memmove (loc , strReplacement, repLen);
          }
        else
          memmove (loc, loc + toRepLen, strlen(loc + toRepLen) +1 ); // Removing
      }
      else
      return NULL; // return NULL if strToReplace is empty.
    }
  return loc;
}

I noticed you had the following in your code:
 // Is there something to replace.
    if ( repLength > 0 )

I have:
if(toRepLen != 0)

Is it possible to have strlen return a negative number?

Thanks,
ibanja
0
 
PaulCaswellCommented:
Hi ibanja,

>>Is it possible to have strlen return a negative number?
Good point but I cant imagine any situation where it would.

My reasons for using:

if(toRepLen != 0)

rather than

if(toRepLen > 0)

is that the code that it guards is provably null in this case but I am allowing all other possibilities to fall through and either work or crash-and-burn. Optimisation, in my opinion, should not hide bugs, it should only short-cut the normal process.

This code is good now! :-) Interesting how it finally came around to something very close to my original but getting here has been a good learning experience for both of us. Thankyou for the exercise :-)

Paul
0
 
ibanjaAuthor Commented:
Hi Paul,

Thank you! I now feel a lot more comfortable with string manipulation thanks to your help.

Much appreciated,
ibanja
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 18
  • 11
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now