Gustavo Marmentini
Gustavo Marmentini

Reputation: 73

Replace substring case insensitive in C++

I need to replace a substring in a string. For example:

Input:

Always

Never

I will always run. ALWAYS!

Output:

I will never run. NEVER!

replace and find work fine. However, the problem is the case sensitive. I have this simple function to do that, but this is incomplete.

string subTag(string s,string a,string b)
{
   while(s.find(a)!=-1){
        s.replace(s.find(a), a.size(), b);
   }

   return s;
}

How can I make the search process case insensitive?

Upvotes: 1

Views: 3311

Answers (3)

Johan
Johan

Reputation: 106

If you want to replace all substrings, consider the following algorithm.

It avoids infinite loops for calls like "subTag( "T_T", "t", "ttt" );"

std::string subTag( std::string s, std::string a, const std::string& b )
{
    if( a.empty() )
        return s;

    std::string res = s;
    std::transform( s.begin(), s.end(), s.begin(), ::tolower );
    std::transform( a.begin(), a.end(), a.begin(), ::tolower );

    size_t pos = s.rfind( a );
    while( pos != std::string::npos )
    {
        res.replace( res.begin() + pos, res.begin() + pos + a.length(), b );

        if( pos == 0 )
            return res;

        pos = s.rfind( a, pos - 1 );
    }

    return res;
}

Upvotes: 0

Humam Helfawi
Humam Helfawi

Reputation: 20284

Convert both the original string and the search phrase to lower case, then search:

string subTag(string s,string a,string b){
   std::string lower_s;
   std::transform(s.begin(), s.end(), lower_s.begin(), ::tolower);
   std::transform(a.begin(), a.end(), a.begin(), ::tolower);
   auto position=lower_s.find(a);
   while(position!=std::string::npos){
        s.replace(position, a.size(), b);
        position=lower_s.find(a);
   }
   return s;
}

Notes:

  1. You have to keep the original s since you need to return it without changing its case.
  2. You can change the case of a directly since you are not using it anymore.
  3. you do not need to change the case of b since you are not using it to search at all.

Upvotes: 3

Temple
Temple

Reputation: 1631

With c++11, try sth like this:

string subTag(string s,string a, string b)
{
    auto pos = std::search(s.begin(), s.end(), a.begin(), a.end(), [](const char c1, const char c2){ return (std::tolower(c1)) == (std::tolower(c2));});
    if(pos == s.end())
        return "";
    auto pos2 = pos;
    std::cout << *pos << std::endl;
    std::advance(pos2, a.size());
    s.replace(pos, pos2, b);

   return s;
}

Upvotes: 2

Related Questions