C ++ Primer第5版练习3.24 - 向量中的迭代器

时间:2014-11-05 18:39:28

标签: c++ vector iterator

我刚开始使用Lippman,Lajoie& amp; 2014年9月Moo的C ++ Primer第五版(第5版,2014年5月)。我可以在那本书中做一些练习,有些我不得不在这里寻求帮助,在这一次我被困了几天。我搜索了谷歌,博客和其他论坛,什么都没有,所以我向你寻求帮助。这是第113页的练习3.24,它与第105页的练习3.20一样,但是使用了迭代器:

  

将一组整数读入矢量。打印每对相邻元素的总和。更改程序,使其打印第一个和最后一个元素的总和,然后是第二个和倒数第二个的总和,依此类推。

按照要求使用迭代器,我可以做第一部分:

#include <iostream>
#include <vector>

using std::cin; using std::cout; using std::endl; using std::vector;

int main()
{
   vector<int> lista;
   int num_entra = 0;

   while (cin >> num_entra)
       lista.push_back(num_entra);


   cout << "Sum of adjacent pairs: " << endl;
   for (auto it = lista.begin(); it != lista.end() - 1; ++it)
   {
       *it += *(it + 1);
       cout << *it << ' ';
   }

   return 0;
}

上面的代码按预期工作,但是我需要将第一个,最后一个,第二个和倒数第二个等等相加的部分有一个我无法解决的问题:

int main()
{
   vector<int> lista;
   int num_entra = 0;

   while (cin >> num_entra)
       lista.push_back(num_entra);


   auto ult = lista.end();

   cout << "Sum of the first and last elements until the center: " << endl;
   for (auto it = lista.begin(); it != lista.end() - 1; ++it)
   {
       *it = *it + *(--ult);
       cout << *it << ' ';
   }

   return 0;
}

如果用户输入1 2 3 4 5 6,程序会添加1 + 6,2 + 5和3 + 4, 但随后它将最后的结果(7)加上5,然后加上6,我似乎无法找到一种方法来阻止这种行为。我能做什么,程序只显示每对的一个总和,直到列表的中心? 提前谢谢。

5 个答案:

答案 0 :(得分:2)

执行此操作的一种方法是使用两个迭代器

auto front = lista.begin();  // start at front and increment
auto back = lista.end() - 1; // start at back and decrement
for (;
     back > front;     // stop when the iterators cross each other
     ++front, --back)
{
    int total = *front + *back;
    std::cout << total << ' ';
}

答案 1 :(得分:0)

我的五美分。只有代替显式初始化的矢量,你应该像你一样为它输入值。

#include <iostream>
#include <vector>

int main() 
{
    std::vector<int> v = { 1, 2, 3, 4, 5 };

    if ( !v.empty() )
    {
        auto first = v.cbegin(), last = v.cend();
        do
        {
            std::cout << *first + *--last;
        } while ( first++ != last );
    }

    return 0;
}

输出

666

这种方法也可以用于std::list

如果你需要跳过中间奇数元素,那么没有随机访问迭代器的容器的一般方法如下

#include <iostream>
#include <vector>

int main() 
{
    std::vector<int> v = { 1, 2, 3, 4, 5 };

    for ( auto first = v.cbegin(), last = v.cend(); 
          first != last && first != --last;
          ++first )
    {
        std::cout << *first + *last;
    }

    std::cout << std::endl;

    return 0;
}

由于向量具有随机访问迭代器,因此可以使用operator <

重写代码
#include <iostream>
#include <vector>

int main() 
{
    std::vector<int> v = { 1, 2, 3, 4, 5 };

    if ( !v.empty() )
    {
        for ( auto first = v.cbegin(), last = v.cend(); 
              first < --last;
              ++first )
        {
            std::cout << *first + *last;
        }

        std::cout << std::endl;
    }
    return 0;
}       

在这两种情况下,输出都是

66

答案 2 :(得分:0)

您的代码的问题在于您在通过解除引用迭代器来计算总和时修改向量(可能不是问题,但这可能是不必要的副作用)并且您甚至没有停止循环've'超越了“向量的中间。”

一个简单的版本可能是

auto front = lista.begin();
auto back = lista.end() - 1;
for (; back > front; ++front, --back)
{
    int total = *front + *back;
    std::cout << total << ' ';
}

但这不会处理奇数个元素,如1 2 3 4 5 6 7(中心4不会被打印)。如果你不想要任何“相同的元素”对,这很好,这个解决方案将处理你需要的每个案例,否则继续。

固定版本可能是

auto front = lista.begin();
auto back = lista.end() - 1;
for (; back >= front; ++front, --back)
{
    if (front == back)
        cout << *front;
    else {
        int total = *front + *back;
        std::cout << total << ' ';
    }
}

但是这不处理空列表[]

这个解决方案可以处理两者,虽然它更复杂:

auto it = lista.begin();
    auto ult = lista.rbegin();
    size_t dist;
    for ( ; it != lista.end() && // I have a valid front iterator
            ult != lista.rend() && // I have a valid back iterator
            (dist = std::distance(it,ult.base()), dist) > 0; // Their distance is greater than 0 (1 is included)
    ++it,++ult ) {
        if (dist == 1)
            cout << *it;
        else
            cout << *it + *ult << ' ';
    }

答案 3 :(得分:0)

除了递减一个迭代器而递减另一个迭代器之外,我认为最好的方法是使用 reverse 迭代器。

auto it = list.begin();
auto rit = list.rbegin(); // a "reverse iterator"
while (it < rit.base()) {
  cout << *it++ + *rit++ << ' ';
}

使用反向迭代器意味着您不必担心由于开始和结束之间的不对称而导致的任何“逐个”调整。

答案 4 :(得分:0)

这也是一种方法,其中mid是最接近数组中间的迭代器,它也常用于二进制搜索实现:

  auto e = lista.end() - 1;
  auto mid = lista.end() + (lista.begin() - lista.end()) / 2;
  for (auto i = lista.begin(); i != mid; ++i, --e){
    cout << *i << "+" << *e << " = " << (*i)+(*e) << endl;
  }

输入:1 2 3 4 5 6 7 8 9;

职位/指数:0 1 2 3 4 5 6 7 8 9

mid =(0 - 10)/ 2 =&gt; -5 + 10 =&gt; 5 循环读取后,循环停止。

并且在索引5处是数字6.因此当循环到达最接近中间的迭代器时循环停止:

i != mid;

 /*Output*/
 1+9 = 10
 2+8 = 10
 3+7 = 10
 4+6 = 10
 5+5 = 10

PS。我建议你检查矢量是否为空。