Reputation: 30118
C++20 added starts_with, ends_with to std::string.
Is there a nice way to get it to be case insensitive?
Note that perf matters so I do not want to lowercase/uppercase both strings(or std::min(len1, len2)
parts of them).
Unlike regular <algorithm>
algorithms starts_with
has no overload with comparator so I see no nice way to do this.
And I kind of understand that 90+% of cases are case sensitive, and that member fns in C++ are avoided unless extremely useful... so I know why this limitation exists, I am just curious if something relatively readable can be hacked together in C++20 without me manually calling std::equal(or ranges version of equal) with custom comparator.
Upvotes: 1
Views: 3172
Reputation: 41
I also faced this problem recently.
If you don't mind using boost, there is istarts_with and iends_with functions.
They do exactly what you need.
Upvotes: 2
Reputation: 16690
std::mismatch(s1.begin(), s1.end(), s2.begin(), s2.end(), <comparator>)
will do what you want. You have to write the case-insensitve comparator, but I'm sure you can figure that out.
Upvotes: 1
Reputation: 123084
I was curious to see how the suggestion to apply this answer works out. This is the result.
Code from said answer:
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;
There the answer suggested to use ci_string
instead of std::string
. Here we just want to create ci_views
to std::string
s:
typedef std::basic_string_view<char, ci_char_traits> ci_string_view;
int main()
{
std::string x{"ABCD"};
std::string y{"abcd"};
std::cout << ci_string_view{x.begin(),x.end()}.ends_with(ci_string_view{y.begin(),y.end()});
}
Output:
1
Upvotes: 2