【问题标题】:Find element in a vector with previous and next element equal to 0在向量中查找前一个和下一个元素等于 0 的元素
【发布时间】:2022-01-08 09:48:05
【问题描述】:

我想通过一个给定的整数向量,找到一个整数,nextprevious整数的值为0。

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> sample = { 0,3,0 };
    for (int i : sample)
    {
        if (sample[i - 1] == sample[i + 1] == 0)
        {
            cout << "hello";
        }
    }
}

但是,我不断收到“向量下标超出范围”错误。我认为这是因为当i 为0 时,sample[-1] 不存在,与i = 2 相同。

有没有简单的解决方法?

【问题讨论】:

  • 您的意思是使用基于索引的循环,例如for (size_t i = 1; i &lt; sample.size() - 1; ++i)
  • 您误解了基于范围的forisample 的值,而不是索引。也就是说,i 的值将分别为030,而不是012。但是,您怀疑尝试访问 sample[-1] 不正确是有根据的,当您重写代码以使用索引时,您应该小心避免这种情况。
  • 你的解释是错误的。 i 被分配了030,而不是012,所以在sample[i] 中使用它作为索引 不会不要做你认为应该做的事。
  • i 不是从 0 到 size-1 的值。它不是一个索引。 i 是被迭代的当前值。在这种情况下,i 的值是03,然后是0。此外,您的逻辑存在缺陷,因为它假定每个元素都是前后元素。如果i 索引,那么当i 是向量中的第一个或最后一个索引时,您将检查越界索引。
  • 不幸的是,Ranged for 循环不允许您使用访问元素的索引;你可以使用迭代器,但不确定你是否已经了解了这些;否则,通过索引循环循环的“标准”可以工作。 if (sample.size() &gt; 2u) { for (auto p1 = sample.begin(), p2 = p1 + 2; p2 != sample.end(); ++p1, ++p2) { if (*p1 == 0 &amp;&amp; *p2 == 0) { std::cout &lt;&lt; "hello"; } }}

标签: c++ for-loop vector


【解决方案1】:

您在这里遇到了两个问题。

第一个是使用 range-for 循环表示法,变量 i 对应于数组值 0、3 和 0。而不是它们的索引。

第二个问题是,如果您从索引 0 迭代到末尾,您将检查索引 -13,它们超出了向量的范围。

这里的代码以两种方式解决问题,第一种使用索引,第二种使用迭代器。对于第二个,您有效地将p 视为指向列表中当前项目的指针。我把清单加长了一点,以便提供更多案例。它输出整数 25 被零包围。

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> sample = { 0, 3, 6, 0, 2, 0, 5, 0 };
    for(int i = 1; i < sample.size() - 1; i++){
        if(sample[i-1] == 0 && sample[i+1] == 0)
            cout << "integer " << sample[i] << " surrounded by 0\n";
    }

    for(std::vector<int>::iterator p = sample.begin() + 1; p != sample.end() - 1; p++){
        if(*(p-1) == 0 && *(p+1) == 0)
            cout << "integer " << *p << " surrounded by 0\n";
    }
}

对于第二个示例,std::vector&lt;int&gt;::iterator 经常更改为 auto 以更短。

【讨论】:

    【解决方案2】:

    这个范围基于for循环

    for (int i : sample)
    {
        if (sample[i - 1] == sample[i + 1] == 0)
        {
            cout << "hello";
        }
    }
    

    没有意义,因为使用了向量的值作为向量的索引。

    基于范围的for循环不适合这样的任务。

    您可以使用例如标准算法std::adjacent_find

    这是一个演示程序。

    #include <iostream>
    #include <vector>
    #include <iterator>
    #include <algorithm>
    
    int main() 
    {
        std::vector<int> v = { 0, 1, 0, 2, 0, 3, 0 };
        
        auto condition = []( const auto &a, const auto &b )
        {
            return a != 0 && b == 0;
        };
        
        if ( not v.empty() )
        {
            for ( auto current = std::next( std::begin( v ) ), last = std::end( v ); 
              ( current = std::adjacent_find( current, std::end( v ), condition ) ) != last;
              std::advance( current, 2 ) )
            {
                if ( *std::prev( current ) == 0 )
                {
                    std::cout << *prev( current ) << ", " 
                              << *current << ", " 
                              << *std::next( current ) << '\n';
                }
            }
        }       
        
        return 0;
    }
    

    程序输出是

    0, 1, 0
    0, 2, 0
    0, 3, 0
    

    【讨论】:

      【解决方案3】:

      range-for loop 中,i 设置为数组中每个元素的。它没有设置为每个元素的 index,就像您当前假设的那样。

      您需要改用基于索引的循环:

      #include <iostream>
      #include <vector>
      
      using namespace std;
      
      int main()
      {
          vector<int> sample = ...;
          if (sample.size() > 2)
          {
              for (size_t i = 1; i < sample.size()-1; ++i)
              {
                  if (sample[i-1] == 0 && sample[i+1] == 0)
                  {
                      cout << sample[i] << endl;
                  }
              }
          }
      }
      

      否则,请改用基于迭代器的循环:

      #include <iostream>
      #include <vector>
      
      using namespace std;
      
      int main()
      {
          vector<int> sample = ...;
          if (sample.size() > 2)
          {
              for (auto iter = sample.begin()+1; iter != sample.end()-1; ++iter)
              {
                  if (*(iter-1) == 0 && *(iter+1) == 0)
                  {
                      cout << *iter << endl;
                  }
              }
          }
      }
      

      【讨论】:

      • if (sample.size() &gt; 2) 在第一个示例中不需要。
      • @Eugene 因为循环需要至少 3 个元素才能正常工作,所以预先验证它是有意义的。至少,代码确实需要if (sample.size() &gt; 0)if (!sample.empty()) 以确保sample.size()-1 不会溢出,否则代码将具有未定义的行为
      猜你喜欢
      • 2014-05-21
      • 2017-03-15
      • 2019-11-06
      • 1970-01-01
      • 2018-02-01
      • 1970-01-01
      • 2013-05-29
      • 1970-01-01
      • 2021-08-03
      相关资源
      最近更新 更多