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

Converting a for loop to use std::transform instead

我正在开发一个功能,它目前可以正常工作。

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;
    }
}

这个函数采用的class是一个简单的class,有2个std::string成员变量。当此 class 通过引用传递给 class 时,它采用已设置的 original 字符串并使用它来填充 shifted 字符串在这个函数看到它之前它是空的。当 for 循环完成时,函数结束,class 对象通过引用返回,并带有新更新的 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; }
    );
}

最后我得到了调试断言失败! Window 留言 Expression: cannot seek string iterator past end

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

编辑

我也试过这个,它像第一个循环一样工作:

{
    amount %= 26;

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

}

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

根据 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的容器要预留足够的space,否则在++result

时会超出范围

问题不在于您的 lambda。您的两个代码段之间的区别在于,您的 for 循环使用 operator+= 将元素附加到您的字符串,但您的转换假定元素已经存在。如果要使用转换附加到字符串,则需要使用插入迭代器。特别是一个后插入迭代器。所以不是传递 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; }
    );