将for循环转换为使用std :: transform

时间:2018-03-09 02:58:44

标签: c++ for-loop lambda stdstring

我正在开发一个函数,它目前按原样运行。

void ceasarShift( CeasarText& text, int amount ) {
    // Bound amount to the number of characters in the alphabet
    amount %= 26;

    for ( std::size_t i = 0; i < text._originalText.length(); i++ ) {
        char c = text._originalText[i] + amount;
        text._shiftedText += c;
    }
}

此函数所使用的类是一个具有2个std :: string成员变量的简单类。当这个类通过引用传递给这个类的友元函数时,它接受已设置的original字符串并使用它来填充shifted字符串,该字符串在此函数看到它之前为空。完成for循环后,函数完成,类对象通过引用以新更新的shifted字符串返回,原始文件未经修改。

我在考虑使用std::transformlambda来执行相同的任务。这就是我的尝试。

void ceasarShift( CeasarText& text, int amount ) {
    // Bound amount to the number of characters in the alphabet
    amount %= 26;

    /*for ( std::size_t i = 0; i < text._originalText.length(); i++ ) {
        char c = text._originalText[i] + amount;
        text._shiftedText += c;
    }*/

    std::transform( text._originalText.begin(), text._originalText.end(),
                text._shiftedText.begin(),
                [amount]( unsigned char c ) -> unsigned char { return c + amount; }
    );
}

我最终得到一个Debug Assertion失败!窗口消息Expression: cannot seek string iterator past end

我想知道我的lambda是否错误,或者我是否需要使用std::transform以外的其他内容。

修改

我也试过这个,这就像第一个循环一样:

{
    amount %= 26;

    for ( auto& c : text._originalText )             
        text._shiftedText += (c + amount);

}

我似乎无法让lambda作为std::transform的谓词正常工作。

2 个答案:

答案 0 :(得分:3)

根据this linkstd::transform的行为相当于:

template <class InputIterator, class OutputIterator, class UnaryOperator>
  OutputIterator transform (InputIterator first1, InputIterator last1,
                            OutputIterator result, UnaryOperator op)
{
  while (first1 != last1) {
    *result = op(*first1);  // or: *result=binary_op(*first1,*first2++);
    ++result; ++first1;
  }
  return result;
}

这意味着OutputIterator的容器应该保留足够的空间,否则,当++result

时它会超出范围

答案 1 :(得分:3)

问题不在于你的lambda。两个片段之间的区别在于,for循环使用operator+=将元素附加到字符串,但您的变换假定元素已经存在。如果要使用transform追加到字符串,则需要使用插入迭代器。特别是后插入迭代器。因此,不要传递text._shiftedText.begin(),而是传递std::back_inserter(text._shiftedText)

std::transform( text._originalText.begin(), text._originalText.end(),
                std::back_inserter(text._shiftedText),
                [amount]( unsigned char c ) -> unsigned char { return c + amount; }
    );