Я озадачен тем, почему, очевидно, невозможно сравнить поддиапазон std::string_view
с std::string_view
. Я имею в виду, что они должны быть одного и того же базового типа и, следовательно, сопоставимы друг с другом?
Может кто-нибудь объяснить, почему это не сработает?
https://godbolt.org/z/3Y6zMaTEv
#include <vector>
#include <string_view>
#include <ranges>
#include <algorithm>
int main() {
std::vector<std::string_view> forbidden{"123", "4fe", "bad"};
std::string_view subject = "foo545jdsf4fesub\n55324123434\nsomebadstuff";
for (auto&& line : subject | std::ranges::views::split('\n')) {
std::ranges::any_of(forbidden, [&line](auto&& bad) {
return std::ranges::find(line, bad) != line.end(); // Complains about something being not callable?!
});
}
return 0;
}
@康桓瑋 или, возможно, string_view::find?
@康桓瑋 std::ranges::search по той или иной причине работает, спасибо. Мне бы хотелось понять, почему find не компилируется.
Это потому, что когда вы пытаетесь использовать std::ranges::find(line, bad)
, строка здесь представляет собой диапазон char
, а не std::string_view
. Вот почему сравнение не работает должным образом.
Преобразуйте строку в std::string_view
с помощью вспомогательной функции и используйте ее std::string_view
для выполнения операции поиска.
#include <vector>
#include <string_view>
#include <ranges>
#include <algorithm>
#include <iostream>
std::string_view to_string_view(const std::ranges::range auto& r) {
auto begin = std::ranges::begin(r);
auto end = std::ranges::end(r);
return std::string_view(&*begin, std::ranges::distance(begin, end));
}
int main() {
std::vector<std::string_view> forbidden{"123", "4fe", "bad"};
std::string_view subject = "foo545jdsf4fesub\n55324123434\nsomebadstuff";
for (auto&& line : subject | std::ranges::views::split('\n')) {
std::string_view line_view = to_string_view(line);
bool found = std::ranges::any_of(forbidden, [&line_view](auto&& bad) {
return line_view.find(bad) != std::string_view::npos;
});
std::cout << (found ? "Forbidden string found!" : "No forbidden string.") << std::endl;
}
return 0;
}
Если вы хотите узнать, содержит ли разделенная подстрока запрещенную подстроку, вы можете просто использовать string_view::contains
:
std::vector<std::string_view> forbidden{"123", "4fe", "bad"};
std::string_view subject = "foo545jdsf4fesub\n55324123434\nsomebadstuff";
for (auto line : subject | std::ranges::views::split('\n')) {
if (std::ranges::any_of(forbidden, [line](auto bad) {
return std::string_view(line).contains(bad);
})) {
// match
}
}
std::ranges::contains_subrange(line, bad)
тоже работает
@Калет, я думаю, string_view::contains
немного более эффективен, поскольку специализируется на строках.
почему, по-видимому, невозможно сравнить поддиапазон std::string_view с std::string_view.
Вы не пытаетесь это сделать. Вы пытаетесь сравнить char
с std::string_view
. std::ranges::find
сравнивает отдельные элементы вида «стог сена» на равенство с «иголкой».
Возможно, вас смутил член std::string_view::find
, который выполняет поиск подстроки.
Если вы хотите только узнать, есть ли в строке плохой текст:
for (auto&& line : subject | std::views::split('\n')) {
std::ranges::any_of(forbidden, [&line](auto bad) {
return std::ranges::contains_subrange(line, bad);
});
}
Если вы хотите узнать, где в строке встречается плохое слово:
for (auto&& line : subject | std::views::split('\n')) {
std::ranges::any_of(forbidden, [&line](auto bad) {
auto res = std::ranges::search(line, bad);
// use position of match
return res.size();
});
}
Вы имеете в виду диапазоны::поиск?