У меня возникли проблемы с реализацией использования for_each
Я могу выполнить работу с помощью цикла for, но для понимания я мог бы использовать некоторую помощь с объяснением … У меня пока есть следующая функция …
void clean_entry(const string& orig, string& cleaned) {
size_t start = 0;
size_t end = 0;
while(!isalnum(orig[start]) && start < orig.length())
start++;
end = start;
while(isalnum(orig[end]) && end < orig.length())
end++;
cleaned = orig.substr(start,(end-start));
// I want to replace the following lines with a for_each loop
string::iterator iter;
for(iter = cleaned.begin(); iter != cleaned.end(); iter++)
*iter = tolower(*iter);
}
В моих попытках реализовать цикл for_each для последних трех строк кода в приведенной выше функции я попытался сделать следующее, что дало мне ошибку компиляции …
struct {
void operator()(string::iterator strIter) {
*strIter = tolower(*strIter);
}
} lower;
for_each(cleaned.begin(),cleaned.end(),lower);
std::for_each
применяет функтор к каждый элемент в данном диапазоне. Он передает фактические элементы вашему функтору (*it
), а не сам итератор.
В твоем случае, void operator()(string::iterator strIter)
следует изменить на void operator()(string::value_type& character)
Мне очень нравится ответ Дауфика — это должно сработать.
Если у вас есть компилятор, совместимый с C ++ 11 (-ish;), вы можете избавиться от struct
и просто замените for
цикл с этим:
std::for_each(
cleaned.begin(),
cleaned.end(),
[](char &c) { c = tolower(c); });
PS Так как вы попросили объяснения: последний параметр for_each()
является лямбда-выражением Лямбда-функция будет вызываться один раз для каждого символа в строке. Чтобы разбить его еще дальше:
[]
: пустой набор здесь означает, что ни один из clean_entry()
переменные будут доступны внутри лямбды (если вы хотите сослаться cleaned
внутри лямбда-функции, вы бы использовали [&cleaned]
вместо). (char &c)
(или же (string::value_type& c)
): определяет, как параметр итерации (отдельные символы строки) будет передаваться в лямбда-функцию (по ссылке, поскольку нам нужно ее изменить).{c = tolower(c);}
: тело лямбда-функции, само за себя.PPS Ради полноты: я предполагаю, что это просто для игры с for_each, а не для реального производственного кода, так как tolower()
как используется здесь, не имеет дело с языками, и другие подходы могут быть более краткими / ясными, такими как
for (char &c : cleaned) {
c = tolower(c);
}
или же
std::transform(cleaned.begin(), cleaned.end(), cleaned.begin(), tolower);
.