【问题标题】:C++ decrementing the iteratorC++递减迭代器
【发布时间】:2021-11-21 19:50:56
【问题描述】:

我是 C++ 新手,目前正在学习迭代器。

我编写了以下代码,它将向量中的第一个和最后一个数字相加。

为了减少迭代器,我不得不将变量dec_pointer 减少两次以获得正确的结果。我显然做错了什么,但是什么?

#include <iostream>
#include <vector>
#include <string>

int main()
{
    std::vector<int> vec{1,4,2,6,9,10,17,13,15};
    size_t first_last =0;
    size_t dec_pointer  = vec.size()-1;
    
    for(auto it =vec.cbegin(); it !=vec.cend() && !vec.empty(); ++it)
    {
        first_last = *it + *(it+(dec_pointer--));
        std::cout<<"Add First and Last Digit : "<<first_last<<std::endl;
        dec_pointer--;
    }

    return 0;
}

【问题讨论】:

  • 只需使用for(int i=0; i &lt; vec.size(); ++i) 并跳过所有伪指针废话。在 every 情况下它会更快,并且您可以避免所有疯狂的语法。

标签: c++ vector iterator


【解决方案1】:

如果您要添加第一个和最后一个元素(根据您的文本),则不需要循环,您可以这样做(当然,在检查最小尺寸之后):

first_plus_last = *(vec.cbegin()) + *(vec.cend()-1);

看起来但是您正在尝试添加第一个和最后一个、第二个和最后一个,等等。您必须减少两次的原因是因为您通过向 current 迭代器值(而不是开始迭代器)添加一些内容来获得第二个迭代器值。

例如,为了便于理解,我们假设它们是索引而不是迭代器:

index:  0  1  2  3  4  5  6  7  8
value:  1  4  2  6  9 10 17 13 15

要正确添加第一个(移动)索引和增量值以获得第二个索引,您需要:

index1  index2  index2 as (index1 + delta)
------  ------  --------------------------
     0       8            0 + 8
     1       7            1 + 6
     2       6            2 + 4
... and so on

您可以看到所需的增量每次减少 两个8, 6, 4, ...


但是,与其进行迭代器计算,我会选择从两端向中间运行迭代器。换句话说,是这样的:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec{1, 4, 2, 6, 9, 10, 17, 13, 15};

    if (vec.size() > 0) {
        auto left = vec.cbegin();
        auto right = vec.cend() - 1;
        while (left < right) {
            auto num1 = *left++;
            auto num2 = *right--;
            auto sum = num1 + num2;
            std::cout << "Add (" << num1 << ", " << num2 << "): " << sum << '\n';
        }
        if (left == right) {
            std::cout << "One number left in middle: " << *left << '\n';
        }
    }
}

这对我来说似乎更清晰(如“更容易理解”)代码,输出是:

Add (1, 15): 16
Add (4, 13): 17
Add (2, 17): 19
Add (6, 10): 16
One number left in middle: 9

它还适用于所有可能的向量大小(空、一个元素、偶数个元素和大于一的奇数个元素)。

【讨论】:

  • 你的第一个例子可能更清楚vec.front() + vec.back()
  • 谢谢你的理解更清楚了。
【解决方案2】:

如果在计算最后一个指针时使用vec.cbegin() 而不是it,则不会出现此问题。

first_last = *it + *(vec.cbegin() + dec_pointer--)

【讨论】:

  • 感谢您的帮助。
【解决方案3】:

在第一次循环迭代中,it 指的是第一个元素,dec_pointer 是 8,所以你有:

-----------------------------------------
| 1 | 4 | 2 | 6 | 9 | 10 | 17 | 13 | 15 |
-----------------------------------------
  ^                                  ^ 
  it                                it+8

如果您随后将 it 增加 1 并将 dec_pointer 减少 1 而不是 2,则在第二次迭代中,dec_pointer 现在是 7,您将拥有:

-----------------------------------------
| 1 | 4 | 2 | 6 | 9 | 10 | 17 | 13 | 15 |
-----------------------------------------
      ^                              ^ 
      it                            it+7

如果您随后将 it 增加 1 并将 dec_pointer 减少 1 而不是 2,则在第 3 次迭代中,dec_pointer 现在是 6,您将拥有:

-----------------------------------------
| 1 | 4 | 2 | 6 | 9 | 10 | 17 | 13 | 15 |
-----------------------------------------
          ^                          ^ 
          it                        it+6

等等。因此,如您所见,您使用it+dec_pointer 引用的last 值始终是相同的元素15。这就是为什么你必须将 dec_pointer 减 2 而不是 1 才能得到正确的结果:

-----------------------------------------
| 1 | 4 | 2 | 6 | 9 | 10 | 17 | 13 | 15 |
-----------------------------------------
  ^   ^   ^                ^    ^    ^ 
  it  |   |                |    |   it+8
      |   |                |    |
     it+1 |                | (it+1)+6
          |                |
         it+2           (it+2)+4

话虽如此,我会建议一个替代且更简单的解决方案 - 使用来自 vec.crbegin()reverse_iterator 来访问第二个值,而不是从 vec.cbegin() 偏移前向 iterator,例如:

#include <iostream>
#include <vector>
#include <string>

int main()
{
    std::vector<int> vec{1,4,2,6,9,10,17,13,15};
    auto last_it = vec.crbegin();
    
    for(auto it = vec.cbegin(); it != vec.cend(); ++it, ++last_it)
    {
        int first_last = *it + *last_it;
        std::cout << "Add First and Last Digit : " << first_last << std::endl;
    }

    return 0;
}

Online Demo

或者更简单,完全摆脱it循环迭代器:

#include <iostream>
#include <vector>
#include <string>

int main()
{
    std::vector<int> vec{1,4,2,6,9,10,17,13,15};
    auto last_it = vec.crbegin();

    for(int first : vec)
    {
        int first_last = first + *last_it++;
        std::cout << "Add First and Last Digit : " << first_last << std::endl;
    }

    return 0;
}

Online Demo

【讨论】:

  • 谢谢,使用 crbegin() 很有意义。
猜你喜欢
  • 2021-11-25
  • 1970-01-01
  • 2012-08-16
  • 1970-01-01
  • 2021-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
相关资源
最近更新 更多