Solved

Remove text from string or wstring

Posted on 2001-09-11
19
256 Views
Last Modified: 2013-12-14
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
Comment
Question by:HillRatIn4433
  • 10
  • 4
  • 4
  • +1
19 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 6475255
Try using std::search to find the string, and std::copy to remove the occurance.
0
 

Author Comment

by:HillRatIn4433
ID: 6475271
How would I use std::copy to remove the word?
0
 
LVL 30

Expert Comment

by:Axter
ID: 6475404
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
 
LVL 30

Accepted Solution

by:
Axter earned 300 total points
ID: 6475415
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 6475522
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
 
LVL 30

Expert Comment

by:Axter
ID: 6475721
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
 
LVL 30

Expert Comment

by:Axter
ID: 6475723
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
 
LVL 4

Expert Comment

by:AssafLavie
ID: 6475821
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
 

Author Comment

by:HillRatIn4433
ID: 6476280
AssafLavie,
I tried using T instead of T*, but it did not work that way.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 30

Expert Comment

by:Axter
ID: 6476303
>>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
 
LVL 30

Expert Comment

by:Axter
ID: 6476479
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 6477366
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
 
LVL 30

Expert Comment

by:Axter
ID: 6477412
>>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
 
LVL 30

Expert Comment

by:Axter
ID: 6477461
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 6477758
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
 
LVL 30

Expert Comment

by:Axter
ID: 6478036
>>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
 

Author Comment

by:HillRatIn4433
ID: 6478454
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
 

Author Comment

by:HillRatIn4433
ID: 6478461
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 6480765
>>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

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Here is a helpful source code for C++ Builder programmers that allows you to manage and manipulate HTML content from C++ code, while also handling HTML events like onclick, onmouseover, ... Some objects defined and used in this source include: …
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now