• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 271
  • Last Modified:

Remove text from string or wstring

I'm trying to remove a word from an STL string.
What is the STL method for removing all the occurances of a key word from an STL string or wstring?
0
HillRatIn4433
Asked:
HillRatIn4433
  • 10
  • 4
  • 4
  • +1
1 Solution
 
AxterCommented:
Try using std::search to find the string, and std::copy to remove the occurance.
0
 
HillRatIn4433Author Commented:
How would I use std::copy to remove the word?
0
 
AxterCommented:
Here's a template fuction that can do what you need in for both string and wstring.

template<typename T>
T* RemoveText(T *SrcStart, T *SrcEnd, const T *TargetStart, const T *TargetEnd)
{
     size_t TargetLen = TargetEnd-TargetStart;
     T* i;
     while((i=std::search(SrcStart,SrcEnd,TargetStart,TargetEnd)) != SrcEnd)
     {
          std::copy(i + TargetLen,SrcEnd+1,i);
     }
     return SrcStart;
}
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
AxterCommented:
Here's a complete an example:

#include <iostream>
#include <string>
#include <functional>
#include <algorithm>

template<typename T>
T* RemoveText(T *SrcStart, T *SrcEnd, const T *TargetStart, const T *TargetEnd)
{
     size_t TargetLen = TargetEnd-TargetStart;
     T* i;
     while((i=std::search(SrcStart,SrcEnd,TargetStart,TargetEnd)) != SrcEnd)
     {
          std::copy(i + TargetLen,SrcEnd+1,i);
     }
     return SrcStart;
}

int main(int argc, char* argv[])
{
     std::string s1 = "Hello there World";
     std::string removetxt = "there ";
     RemoveText(s1.begin(),s1.end(),removetxt.begin(), removetxt.end());
     std::cout << s1.c_str() << std::endl;

     std::wstring ws1 = L"Hello there World";
     std::wstring w_removetxt = L"there ";
     RemoveText(ws1.begin(),ws1.end(),w_removetxt.begin(), w_removetxt.end());
     std::wcout << ws1.c_str() << std::endl;
     return 0;
}
0
 
DanRollinsCommented:
If you consider simplicity a virtua, you might consider this alternative;

#include <iostream>
#include <string>
using namespace std ;

string& Remove( string& sSrc, string& sRemove )
{
    int nLen= sRemove.length();

    int j= 0;
    while( (j= sSrc.find(sRemove, j)) != -1 ) {
         sSrc.erase(j,nLen);
    }
    return sSrc;
}

void main()
{
     string s="Hello there world.";
     string s2= "there ";
     string s3= Remove( s, s2);
     cout << s3 << endl     ;
}


-- Dan
0
 
AxterCommented:
FYI:
The function I posted will work with string, wstring and old C-Style variables.

Example:
int main(int argc, char* argv[])
{
     std::string s1 = "Hello there World";
     std::string removetxt = "there ";
     RemoveText(s1.begin(),s1.end(),removetxt.begin(), removetxt.end());
     std::cout << s1.c_str() << std::endl;

     std::wstring ws1 = L"Hello there World";
     std::wstring w_removetxt = L"there ";
     RemoveText(ws1.begin(),ws1.end(),w_removetxt.begin(), w_removetxt.end());
     std::wcout << ws1.c_str() << std::endl;

     char cstyle_str[] = "Hello there World";
     char cstyle_removetxt[] = "there ";
     RemoveText(cstyle_str,cstyle_str+strlen(cstyle_str),cstyle_removetxt, cstyle_removetxt+strlen(cstyle_removetxt));
     std::cout << cstyle_str << std::endl;
     return 0;
}

0
 
AxterCommented:
If you decide to use Dan's method, you might want to change it to a template function so that it can take both string and wstring types.
Example:
template<typename T>
T& Remove( T& sSrc, T& sRemove )
0
 
AssafLavieCommented:
Axter, again you're using T* instead of T as the parameter types of your algorithm. It's better to use T itself (if you remember, we'd discussed this a wihle ago). Take example from the STL algorithms.
0
 
HillRatIn4433Author Commented:
AssafLavie,
I tried using T instead of T*, but it did not work that way.
0
 
AxterCommented:
>>Axter, again you're using T* instead of T
While I agree with you in that using T instead of T* is the preferred method, it is not always possible to use T, and get the desired results.  This is one of those situations.
If I used T, I would have to loose the function's ability to work with both C-Style and C++ style strings.
For my purposes, it is more important to retain this capability, then it is to retain the ability to have the function work with other iterators.
0
 
AxterCommented:
AssafLavie,
Disregard my previous comment.  It can work with just T.

HillRatIn4433,
AssafLavie is right.  You should use T, instead of T*.

>>I tried using T instead of T*, but it did not work that
>>way.
Are you sure you modified all the T* statements?
It should look like the following:
template<typename T>
T RemoveText(T SrcStart, T SrcEnd, const T TargetStart, const T TargetEnd)
{
    size_t TargetLen = TargetEnd-TargetStart;
    T i;
    while((i=std::search(SrcStart,SrcEnd,TargetStart,TargetEnd)) != SrcEnd)
    {
         std::copy(i + TargetLen,SrcEnd+1,i);
    }
    return SrcStart;
}

0
 
DanRollinsCommented:
It is hard for me to imagine a scenario in which I would use such obtuse complicated unreadable crap in order to solve a simple, straightforward problem.  Color me amused.

-- Dan
0
 
AxterCommented:
>>I would use such obtuse complicated unreadable crap

How is it complicated?  I see very little difference in readability between your code and mine.
For your code to work with both string and wstring, it would need to be a template.
With that said here's your code:

template<typename T>
T& Remove( T& sSrc, T& sRemove )
{
   int nLen= sRemove.length();
   int j= 0;
   while( (j= sSrc.find(sRemove, j)) != -1 )
   {
        sSrc.erase(j,nLen);
   }
   return sSrc;
}


Here's my code:

template<typename T>
T RemoveText(T SrcStart, T SrcEnd, const T TargetStart, const T TargetEnd)
{
   size_t TargetLen = TargetEnd-TargetStart;
   T i;
   while((i=std::search(SrcStart,SrcEnd,TargetStart,TargetEnd)) != SrcEnd)
   {
        std::copy(i + TargetLen,SrcEnd+1,i);
   }
   return SrcStart;
}

I don't see your code been all that simplistic, and it doesn't use the standard format that most STL code uses.
Most STL algorithms use the START and END combination.  Your's does not, which makes it incompatible with algorithms and classes that depend on this format.
Also your code uses int, when it should be using size_t.

>>It is hard for me to imagine a scenario in which I would
>>use
How would you remove an occurance of keywords from a C-Style char[] string using your method?
There's a lot of code that still uses the C-Style string.  My function works with the old code as well as the std::string and std::wstring.
0
 
AxterCommented:
DanRollins,
You also should not use -1.  It should be npos.
Example:

template<typename T>
T& Remove( T& sSrc, T& sRemove )
{
   size_t nLen= sRemove.length();
   size_t j= 0;
   while( (j= sSrc.find(sRemove, j)) != T::npos)
   {
        sSrc.erase(j,nLen);
   }
   return sSrc;
}

Even with these modifications, this function still can only work with limited object types.

The function I posted can work with almost any object type.
0
 
DanRollinsCommented:
ob
tuse
un
readable
and I might add, unmaintainable.  

What is a T or a T*?  Why on earth would you want that to appear anywhere in your code?  Are we writing BASIC in 1975?  When the gods of STL came up with that, what were they *THINKing?!?*  When you look at available overloaded member fns, they are filled with _E, _X, Z::_Gibberish<More_Junk>.  Who needs that kind of headache?  

Now imagine that you lead a team of programers who need to work with that code.  They will spend so much time on the cr*p that they won't get the application program out the door.

>>I see very little difference in readability between your code and mine.
Really, now.  Compare...
    RemoveText(s1.begin(),s1.end(),removetxt.begin(), removetxt.end());
to
    Remove( sText, sRemoveText );

Which one do you want to explain to the junior programmer and which one do you want to document?  Remember, honesty counts!

As to handling wstring, I would just write a second override.  The compiler would automatically call it.  As to using char* I'd just use strstr and strcpy in a similar overriden version.

If I ever need to remove certain "keywords" from an array of imaginary numbers or pointers to GUIDs, I'll write another override to handle that.

-- Dan
0
 
AxterCommented:
>>Which one do you want to explain to the junior
>>programmer and which one do you want to document?  
>>Remember, honesty counts!

Honestly, I rather explain the function that looks more like an STL algorithm.  Especially since it's working with STL objects.  This also teaches the junior programmer how to create generic algorithms.

>>As to handling wstring, I would just write a second
>>override.  
You're then making the code harder to maintain.  (Twice as hard).  When ever you have to update or trouble shoot the code, you have two functions to deal with instead of one.

>>As to using char* I'd just use strstr and strcpy in a
>>similar overriden version.
This is more work you're adding to the code, the programmer, and you're making the code more complicated then it has to be.

I know you don't like STL, and I agree that it has an ugly syntax, but it is part of the C++ language whether you like it or not.  
Not using STL would be like not using a burnt right arm only because it's burnt and it looks ugly.
0
 
HillRatIn4433Author Commented:
DanRollins,
I think it's a crappy idea to make multiple functions that can be performed by one template function.
That makes no sense what so ever.  And that's something that an amateur programmer would do.
0
 
HillRatIn4433Author Commented:
Axter,
>>Are you sure you modified all the T* statements?
I don't know what happen, but I must have missed something.  I tried it again and it worked.
Thanks

AssafLavie,
Thanks for your input.
0
 
DanRollinsCommented:
>>That makes no sense what so ever.  And that's something that an amateur programmer would do.

I'm flattered.  I'm usally referred to as a 'rank amateur' so 'amateur' is quite a step up.  Please work a bit harder when you compose your next insult.  Thanks!

-- Dan
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 10
  • 4
  • 4
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now