3

Suppose I have some string, str.

I was to check if str contains a keyword: "samples" However, "samples" could be in any form of capitalization such as: "Samples" "SamPleS", "SAMPLES".

this is what I am trying:

string str = "this is a FoO test";
if (str.find("foo") != std::string::npos){
    std::cout << "WORKS";
}

This does not detect the "FoO" substring. Is there some sort of argument I can pass through to ignore capitalization? Or should I be using something else entirely?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Hani Al-shafei
  • 149
  • 1
  • 2
  • 13
  • The easiest solution is to convert both to the same case, but that may not be the most efficient. – Neil Kirk Nov 27 '15 at 04:41
  • If you intend to handle The World's languages (and not just English), you need to be aware that there is a difference between calling `toupper` (or `tolower`) on each character, and actually converting an entire string to upper (or lower) case. See the [this answer to a vaguely related question](http://stackoverflow.com/a/23281505/1566221). – rici Nov 27 '15 at 05:48

1 Answers1

1

There are a variety of options.

Using boost::algorithm::ifind_first.

First include <boost/algorithm/string/find.hpp> and <string>.

Then use ifind_first as follows.

std::string str = ...;
std::string subStr = ...;
boost::iterator_range<std::string::const_iterator> rng;
rng = boost::ifind_first(str, subStr);

Using char_traits.

struct ci_char_traits : public char_traits<char>
{
    static bool eq(char c1, char c2) { return toupper(c1) == toupper(c2); }
    static bool ne(char c1, char c2) { return toupper(c1) != toupper(c2); }
    static bool lt(char c1, char c2) { return toupper(c1) <  toupper(c2); }
    static int compare(const char* s1, const char* s2, size_t n)
    {
        while( n-- != 0 )
        {
            if( toupper(*s1) < toupper(*s2) ) return -1;
            if( toupper(*s1) > toupper(*s2) ) return 1;
            ++s1; ++s2;
        }
        return 0;
    }
    static const char* find(const char* s, int n, char a)
    {
        while(n-- > 0 && toupper(*s) != toupper(a))
        {
            ++s;
        }
        return s;
    }
};

typedef std::basic_string<char, ci_char_traits> ci_string;

Then you can use it as follows.

ci_string str = ...;
std::string subStr = ...;
auto pos = str.find(subStr.c_str());

Note that the problem with this is the fact that you need to use the c_str function when calling the find function or when assigning a ci_string to a std::string or when assigning a std::string to a ci_string.

Use std::search with a custom predicate

As suggested in the article Case insensitive std::string.find().

Community
  • 1
  • 1
Benilda Key
  • 2,836
  • 1
  • 22
  • 34