2

如果我有一个看起来像这样的数组:

int map[21][28] =
{
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

如何创建一个由该数组中的值组成的较小数组..?
有点像这样:

int zoomedMap[7][7] =
{

    2, 2, 1, 1, 1, 1, 1,
    1, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 1,
    1, 1, 1, 1, 1, 1, 1
};

我不知道这是否有帮助,但是:

  • 我知道两个数组的确切尺寸
  • 我希望可以移动较小的数组位置,最好只更改 X/Y 值
4

4 回答 4

1

希望显而易见的是,您的子阵列实际上只不过是主阵列中的数据“块”(带有一些有趣的分区。假设您正在检查您的边界并且不允许发生越界情况,您可以使用指针数学和有关主数组的一些基本信息来模拟您的子数组。

  • 该块将始终与该位置有一些[row][column]偏移[0][0],因此我们需要这些值(行和列)。
  • 该块具有固定宽度,column+width不会超过您的主阵列宽度。我们需要那个宽度。
  • 该块具有固定高度,因此row+height不会超过您的主阵列高度。我们需要那个高度。
  • 我希望很明显我们需要作为主数组的基地址(在你的情况下map)。

这可能是最好的例子。以下不是一些最终的解决方案。它甚至可能无法满足您需要的 1/10。相反,它旨在让您了解如何仅使用指针、一些偏移量、一些大小和一些算术来获得您正在寻找的东西。没有什么可以阻止您超出可能有害的限制(就像普通数组一样),所以要小心。

// internal rerefential to a submatrix in a larger fixed matrix.
template<typename T>
class Sub2D
{
public:
    template<size_t R, size_t C>
    Sub2D(T(&ar)[R][C], int top, int left, int height, int width)
    : parent(ar[0])
    , row(top)
    , col(left)
    , max_row(R)
    , max_col(C)
    {
        if ((row+width) >= R || (col+height) >= C)
            throw std::out_of_range("");
    }

    // retrieve our subrow offset into the main 2D array
    T* operator [](size_t n)
    {
        // enable at your desire, but as Alex pointed out, all
        // the standard containers let you shoot yourself in the
        // foot with this operator. why not this one too =P
        //if (row+n >= max_row)
        //    throw std::out_of_range("");

        return parent + ((row+n)*max_col + col);
    }

private:
    T* parent;
    size_t row, col;
    size_t max_row, max_col;
};

像这样使用,假设您的问题中的数组是我们所基于的数组:

int main()
{
    // take the submatrix & [6][7] that is 7x7 in dimension.
    Sub2D<int> sub(map, 6,7, 7,7);
    for (size_t i=0;i<7;++i)
    {
        for (size_t j=0;j<7;++j)
            cout << sub[i][j] << ' ';
        cout << endl;
    }
    cout << endl;

    // update an element at location [1][1] of our sub-matrix.
    sub[1][1] = 9;

    // reprint the *entire* main array. it better have updated.
    for (size_t i=0;i<sizeof(map)/sizeof(map[0]);++i)
    {
        for (size_t j=0;j<sizeof(map[0])/sizeof(map[0][0]);++j)
            cout << map[i][j] << ' ';
        cout << endl;
    }
    cout << endl;

    return 0;
}

产生以下输出。

2 2 1 1 1 1 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 1 1 1 1 1 1 

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 2 2 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 9 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

请注意,现在 9 位于我们期望的位置。

显然,您可以向这样的模板类添加更多内容,包括更好的范围检查、移动指针、快照到其他内存缓冲区等,但重点是基本的 get-me-this 子矩阵指针和一些偏移量很难被击败,尤其是在性能方面。

于 2013-01-13T11:25:04.970 回答
0

阅读 Boost 的uBLAS模块。它提供了 Matrix 和 MatrixRange 类,这正是您正在寻找的。

本质上,zoomedMap应该只是一个指向更大矩阵的智能指针,它知道如何取消引用并获得正确的结果。

于 2013-01-13T10:15:35.323 回答
0

你总是可以用循环静态地做到这一点:

const int pos_x = 6, pos_y = 7, size_x = 7, size_y = 7;

int newMap[size_x][size_y] = {0};

for( int i = pos_x; i != pos_x+size_x; ++i ) {
    for( int j = pos_y; j != pos_y+size_y; ++j) {
        newMap[i-pos_x][j-pos_y] = map[i][j];
    }
}

虽然这不是很安全,并且很难动态工作。您可能想用您想要的功能编写一个矩阵包装类;或找到一个已经存在并扩展它(我会开始研究现有矩阵类的 STL 或 Boost)

于 2013-01-13T10:29:00.990 回答
0

根据您的要求,这可能就足够了:

int (*zoomedMap)[28] = reinterpret_cast<int (*)[28]>(&map[X][Y]);

这为您提供了一个标识符,您可以像使用二维数组一样使用它:zoomedMap[i][j]. 您可以通过为其分配新地址轻松地在更大的数组中移动缩放的地图。

这取决于您的 C++ 实现,允许将指向浮点数的指针强制转换为指向浮点数数组的指针,前提是所有引用都保留在原始数组中。这很常见。

zoomedMap指向与 相同的内存map。因此,你不能改变一个而不改变另一个。如果你想这样做,你需要制作一个副本。

于 2013-01-13T13:38:08.707 回答