如何在C ++中访问数组中的相邻元素?

时间:2016-04-07 16:18:01

标签: c++ arrays operator-overloading

我会实现一个函数,访问给定元素的相邻元素。

这是一个简单的例子:对距离一维数组中给定元素的半径距离内的元素求和。 C代码是:

int sum(int *elem_ptr, int radius) {
    int sum = 0;
    for (int *ptr = elem_ptr - radius; ptr <= elem_ptr + radius; ptr++) {
        sum += *ptr; 
    }
    return sum;
}

但是,上面的代码没有检查ptr用完数组边界的情况。所以,我想自动提供这种边界检查功能。换句话说,我们不需要将边界检查代码添加到上面的代码中。

我正在考虑使用C ++运算符重载,它允许'*'运算符检查边界。但是,我不知道该怎么做。

2 个答案:

答案 0 :(得分:1)

在C ++中,在容器上使用迭代器是可行的方法,而不是像代码示例中所示进行指针运算。 迭代器也比原始索引更好,因为它使您的代码与任何容器兼容(例如,集合或映射没有索引)。

使用最近的STL,可用于操作迭代器的工具包已变得非常通用:

  • std::prev(iterator, n)移动迭代器n向后排列 (向集合的开头)(ref)
  • std::next(iterator, n)移动前进 (ref)
  • std::distance(a, b)计算迭代器之间的元素数量,这对于检查您是否超出范围非常有用(ref)

使用迭代器还会产生另一个好的副作用:您将能够使用标准库中已有的众多算法之一,例如来自<algorithm><numeric>

事实证明,有一个函数已经计算了一系列元素的总和:std::accumulate。您需要做的就是根据您的需要(ref. on accumulate)使用它。

这是一个不完美的实现的开始,但大部分时间都应该可以。

#include <functional>
#include <numeric>

int sum(const std::vector<int>& v,
        const std::vector<int>::const_iterator elem,
        size_t radius)
{
    auto first_radius = (std::abs(std::distance(std::cbegin(v), elem)) < radius)
                        ? std::cbegin(v)
                        : std::prev(elem, radius);

    auto last_radius = (std::abs(std::distance(elem, std::cend(v))) < radius)
                       ? std::cend(v)
                       : std::prev(elem, radius);

    return std::accumulate(first_radius, last_radius, 0, std::plus<int>());
}

如果您不习惯语法,这似乎有点压倒性,但大部分都是绑定检查。 first_radiuslast_radius是你“mask”半径的边界的迭代器,确保它们不在向量的“外部”(请注意,我不确定此代码是100%的bug-自由)。之后,让std::accumulate为我们做繁重的工作!

您可以使用以下代码:

std::vector<int> x = { 0, 1, 0, 1, 0, 1};
const int a = sum(x, std::next(std::cbegin(x), 3), 15);
const int b = sum(x, std::prev(std::cend(x), 1), 2);

根据您对语言的熟悉程度,可能会有很多信息。值得花些时间查看我在这里使用的函数的文档,因为它实际上是惯用的方法(对于C ++,请注意)。

作为结束语:您必须注意到我在我的示例中使用了std::vector。好吧,迭代器很好用:我们可以使这个函数完全与容器无关!

使用模板,它可以用于地图,数组,集合,自定义容器...您可以命名。但这次应该足够了......如果你有兴趣的话,不要介意问我这个模板技巧。

玩得开心!

答案 1 :(得分:0)

由于数组很痛苦,我将首先使用std::vector提供解决方案。

int sum_vector_neighbor(const std::vector<int>& values, 
                        unsigned int position,  // negative positions are weird. 
                        unsigned int radius)    // negative radii are weird.
{
   if (values.empty())
   {
     return 0;
   }
   const unsigned int size = values.length();
   unsigned int start_index = 0U;
   unsigned int end_index = size - 1;
   if (radius < position)
   {
     start_index = position - radius;
   }
   if ((position + radius) < size)
   {
     end_index = position + radius;
   }
   sum = 0;
   for (; start_index < end_index; ++start_index)
   {
      sum += values[start_index];
   }
   return sum;
}

上面的解决方案是使用索引而不是指针,因为索引比指针更容易比较。

使用索引的习惯用法可以应用于数组。对于阵列版本,您需要另外传递数组的容量,因为当数组转换为指向第一个元素的指针时,capacity属性将被删除。

我不建议使用指针,因为你必须从指针中减去半径值(这是一个有效的操作),但是比较小于或大于不是所有平台支持的操作< / em>的。