Case insensitive std::string.find()

前端 未结 10 1934
挽巷
挽巷 2020-11-27 02:47

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 s

相关标签:
10条回答
  • 2020-11-27 03:31

    I love the answers from Kiril V. Lyadvinsky and CC. but my problem was a little more specific than just case-insensitivity; I needed a lazy Unicode-supported command-line argument parser that could eliminate false-positives/negatives when dealing with alphanumeric string searches that could have special characters in the base string used to format alphanum keywords I was searching against, e.g., Wolfjäger shouldn't match jäger but <jäger> should.

    It's basically just Kiril/CC's answer with extra handling for alphanumeric exact-length matches.

    /* Undefined behavior when a non-alpha-num substring parameter is used. */
    bool find_alphanum_string_CI(const std::wstring& baseString, const std::wstring& subString)
    {
        /* Fail fast if the base string was smaller than what we're looking for */
        if (subString.length() > baseString.length()) 
            return false;
    
        auto it = std::search(
            baseString.begin(), baseString.end(), subString.begin(), subString.end(),
            [](char ch1, char ch2)
            {
                return std::toupper(ch1) == std::toupper(ch2);
            }
        );
    
        if(it == baseString.end())
            return false;
    
        size_t match_start_offset = it - baseString.begin();
    
        std::wstring match_start = baseString.substr(match_start_offset, std::wstring::npos);
    
        /* Typical special characters and whitespace to split the substring up. */
        size_t match_end_pos = match_start.find_first_of(L" ,<.>;:/?\'\"[{]}=+-_)(*&^%$#@!~`");
    
        /* Pass fast if the remainder of the base string where
           the match started is the same length as the substring. */
        if (match_end_pos == std::wstring::npos && match_start.length() == subString.length()) 
            return true;
    
        std::wstring extracted_match = match_start.substr(0, match_end_pos);
    
        return (extracted_match.length() == subString.length());
    }
    
    0 讨论(0)
  • 2020-11-27 03:33

    If you want “real” comparison according to Unicode and locale rules, use ICU’s Collator class.

    0 讨论(0)
  • 2020-11-27 03:34

    wxWidgets has a very rich string API wxString

    it can be done with (using the case conversion way)

    int Contains(const wxString& SpecProgramName, const wxString& str)
    {
      wxString SpecProgramName_ = SpecProgramName.Upper();
      wxString str_ = str.Upper();
      int found = SpecProgramName.Find(str_);
      if (wxNOT_FOUND == found)
      {
        return 0;
      }
      return 1;
    }
    
    0 讨论(0)
  • 2020-11-27 03:36

    Why not just convert both strings to lowercase before you call find()?

    tolower

    Notice:

    • Inefficient for long strings.
    • Beware of internationalization issues.
    0 讨论(0)
提交回复
热议问题