for_each实现与tolower

时间:2013-09-26 00:42:09

标签: c++ foreach tolower

我在实现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);

2 个答案:

答案 0 :(得分:1)

std::for_each将一个仿函数应用于给定范围内的每个元素。它将实际元素传递给您的仿函数(*it),而不是迭代器本身。

在您的情况下,void operator()(string::iterator strIter)应更改为void operator()(string::value_type& character)

答案 1 :(得分:1)

我真的很喜欢dauphic的答案 - 这应该可行。

如果你有一个符合C ++ 11的(-ish;)编译器,你可以摆脱struct,只需用这个替换for循环:

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

PS因为您要求解释:for_each()的最后一个参数是lambda表达式。 lambda函数将为字符串中的每个字符调用一次。进一步分解:

  • []:这里的空集意味着lambda内部都不能访问clean_entry()个变量(如果你想在lambda函数中引用cleaned,你会改为使用[&cleaned])。
  • (char &c)(或(string::value_type& c)):定义如何将迭代参数(字符串的各个字符)传递给lambda函数(通过引用,因为我们需要修改它)。 / LI>
  • {c = tolower(c);}:lambda函数的主体,不言自明。

PPS为了完整起见:我假设这只是为了使用for_each,而不是用于实际的生产代码,因为这里使用的tolower()不处理语言环境和其他方法可以更简洁/清晰,例如

  for (char &c : cleaned) {
        c = tolower(c);
  }

std::transform(cleaned.begin(), cleaned.end(), cleaned.begin(), tolower);