Search code examples
c++stringstlcase-insensitivewstring

Case insensitive std::string.find()


I am using std::string's find() method to test if a string is a substring of another. Now I need case insensitive version of the same thing. For string comparison I can always turn to stricmp() but there doesn't seem to be a stristr().

I have found various answers and most suggest using Boost which is not an option in my case. Additionally, I need to support std::wstring/wchar_t. Any ideas?


Solution

  • You could use std::search with a custom predicate.

    #include <locale>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    // templated version of my_equal so it could work with both char and wchar_t
    template<typename charT>
    struct my_equal {
        my_equal( const std::locale& loc ) : loc_(loc) {}
        bool operator()(charT ch1, charT ch2) {
            return std::toupper(ch1, loc_) == std::toupper(ch2, loc_);
        }
    private:
        const std::locale& loc_;
    };
    
    // find substring (case insensitive)
    template<typename T>
    int ci_find_substr( const T& str1, const T& str2, const std::locale& loc = std::locale() )
    {
        typename T::const_iterator it = std::search( str1.begin(), str1.end(), 
            str2.begin(), str2.end(), my_equal<typename T::value_type>(loc) );
        if ( it != str1.end() ) return it - str1.begin();
        else return -1; // not found
    }
    
    int main(int arc, char *argv[]) 
    {
        // string test
        std::string str1 = "FIRST HELLO";
        std::string str2 = "hello";
        int f1 = ci_find_substr( str1, str2 );
    
        // wstring test
        std::wstring wstr1 = L"ОПЯТЬ ПРИВЕТ";
        std::wstring wstr2 = L"привет";
        int f2 = ci_find_substr( wstr1, wstr2 );
    
        return 0;
    }