2013-09-26 5 views
0

У меня возникли проблемы с использованием for_each, я могу выполнить работу с помощью цикла for, но для понимания я мог бы использовать некоторую помощь с объяснением ... У меня есть следующие функции до сих пор ...for_each с tolower

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); 
+0

У вас есть C++ 11 (т. Е. Лямбда), доступный для вас? – us2012

ответ

1

std::for_each применяет функтор к каждый элемент в данном диапазоне. Он передает действительные элементы вашему функтору (*it), а не сам итератор.

В вашем случае, void operator()(string::iterator strIter) должен быть изменен на void operator()(string::value_type& character)

1

Мне очень нравится ответ dauphic в - это должно работать.

Если у вас есть C++ 11-совместимый (-ish;) компилятор, вы можете избавиться от struct, а просто заменить for петлю с этим:

std::for_each(
    cleaned.begin(), 
    cleaned.end(), 
    [](char &c) { c = tolower(c); }); 

PS Так как вы просили для объяснения: последний параметр for_each() - это лямбда-выражение. Лямбда-функция будет вызываться один раз для каждого символа в строке. Для того, чтобы разбить его еще дальше:

  • []: пустое множество здесь означает, что ни одна из переменных clean_entry() «s будет доступна внутри лямбда (если вы хотите, чтобы ссылаться на 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); 

.