'How to check if string contains substring that matches given predicate?
I'm trying to achieve the behavior similar to std::basic_string<CharT>::find(), except it has to accept a predicate that has to match the searched string.
The signature will look like this:
template <class StringType, class Predicate
size_t search(const StringType& where, Predicate pred, size_t pos, size_t n) {/*...*/}
template <class StringType, class Predicate
size_t search(const StringType& where, Predicate pred, size_t pos = 0) {/*...*/}
Note I'm using size_t instead of typename StringType::size_type to save space on screen.
e.g. calling the function will look something like this:
search("Hello world"s, [](auto&& str) {
return str[0] == 'l'
and str[1] == 'l'
and str.size() > 3;
});
and will return the value 2.
In this particular example, I can use a regex to find the substring, but I want to be able to write a general predicate.
Solution 1:[1]
Try something like this:
template <class StringType, class Predicate, class SizeType = typename StringType::size_type>
SizeType search(const StringType& where, Predicate pred, SizeType pos, SizeType n)
{
if (n > 0 && pos < where.size())
{
auto start = where.c_str(),
ptr = start + pos,
stop = ptr + std::min(where.size() - pos, n);
do
{
if (pred(ptr, stop - ptr))
return ptr - start;
}
while (++ptr < stop);
}
return StringType::npos;
}
template <class StringType, class Predicate, class SizeType = typename StringType::size_type>
SizeType search(const StringType& where, Predicate pred, SizeType pos = 0)
{
return search(where, pred, pos, where.size()-pos);
}
search("Hello world"s,
[](auto&& str, auto n) {
return n > 3 &&
str[0] == 'l' &&
str[1] == 'l';
}
);
Alternatively, using std::string_view for the predicate argument:
template <class StringType, class Predicate, class SizeType = typename StringType::size_type>
SizeType search(const StringType& where, Predicate pred, SizeType pos, SizeType n)
{
if (n > 0 && pos < where.size())
{
std::basic_string_view<typename StringType::value_type> sv(where.c_str()+pos, std::min(where.size() - pos, n));
do
{
if (pred(sv))
return pos;
++pos;
sv = sv.substr(1);
}
while (!sv.empty());
}
return StringType::npos;
}
template <class StringType, class Predicate, class SizeType = typename StringType::size_type>
SizeType search(const StringType& where, Predicate pred, SizeType pos = 0)
{
return search(where, pred, pos, where.size()-pos);
}
search("Hello world"s,
[](auto&& str) {
return str.size() > 3 &&
str[0] == 'l' &&
str[1] == 'l';
}
);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
