数组由另一个数组内的值组成

时间:2013-01-13 09:39:51

标签: c++ arrays multidimensional-array

如果我有一个如下所示的数组:

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 个答案:

答案 0 :(得分: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子矩阵指针和一些偏移很难被击败,特别是对于性能。

答案 1 :(得分:0)

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

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

答案 2 :(得分: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)

答案 3 :(得分:0)

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

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

这为您提供了一个可以使用的标识符,就好像它是一个二维数组:zoomedMap[i][j]。您可以通过为其指定新地址轻松移动较大阵列中的缩放地图。

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

它使zoomedMap指向与map相同的内存。因此,你不能在不改变另一个的情况下改变一个。如果你想这样做,你需要复制一份。