c ++使用2d数组

时间:2011-12-28 10:21:36

标签: c++ arrays c++11

目前我正在学习C ++,我一直在努力为学习目的创建一个简单的图像处理库。

我的一个功能是侵蚀图像。作为输入,它有两个2d数组,并返回另一个2d数组。所有这些数组都是可变大小的。让我们举例说明我想要实现的目标。

int image[5][5] = 
{
 {'0', '0', '0', '0','0'},
 {'0', '1', '1', '1','0'},
 {'0', '0', '1', '0','0'},
 {'0', '1', '1', '1','0'},
 {'0', '0', '1', '0','0'},
 };

int kernel[3][3] = 
{
 {'0', '1', '0'},
 {'1', '1', '1'},
 {'0', '1', '0'},
 };

然后我想把它们传递给我的函数(这不会编译,但它可以作为我想要的一个例子)。

int** erode(int image[][], int kernel[][]);

到目前为止,我已经阅读了很多相关内容。我读过的只是列可以是可变长度的,但行不能。所以我应该将其更改为以下内容:

int** erode(int image[][5], int kernel[][3]);

但这并不是我想要的,因为好吧,图像可以是10 * 10,内核可以是5 * 5。所以这在这种情况下也不是最佳的。

然后我读到的是创建一个类,它在内部将图像存储为1d数组并使其看起来像2d数组。我也读过有关使用Boost.MultiArray类来执行此操作的信息。但我对此也不太满意。因为那时我强迫使用它的人也使用这些类。而且我认为这对于看似非常简单的事情(至少在C#中)会产生很多复杂性。

说实话,我无法想象没有更简单的方法可以做到这一点。最好我只说使用标准C++11库中的类/方法。 您如何解决这个问题?

蒂莫

4 个答案:

答案 0 :(得分:4)

看看你是否可以使用模板,例如:

template<int N>
void f(int (&arr)[N][N]);

如果数组有编译时限。 但实际上你应该考虑提升,犰狳或者电视

答案 1 :(得分:3)

我会将数组作为指针传递,并传递另一个定义数组大小的参数。

int** erode(int* image, size_t imageSize, int* kernel, size_t kernelSize);

数组只是内存中的连续变量列表,而image[5][5]等数组变量只指向数组的第一个元素。将已显示的数组传递给您将使用的函数。

int** ret = errode(image, 5, kernel, 3);

使用它时要小心,因为它很容易导致分段错误,但正确使用时会很好。这也假设数组是方形的,为了克服这个限制,只需传入另一个描述数组其他维度的参数。

<强>更新

我看到Anycorn发布了一个非常好的解决方案。他是一个更安全的解决方案,但是需要你在编译时知道数组的大小。如果是这种情况,我会建议你使用他所说的。

答案 2 :(得分:2)

您撰写的关于内部存储1D阵列的内容基本上是最佳解决方案。使用二维阵列通常很危险,很容易导致错误。如果您不想创建整个班级,请考虑:

const int SizeX = 10, SizeY = 10;
int Array[SizeX*SizeY];
inline int& Get (int x, int y) { return Array[SizeX*y+x]; }

当然,这是一个非常简单的例子,但通常会解决很多错误。

struct MyOwnArray
{
    int SizeX, int SizeY;
    int* Data;
    inline int& Get (int x, int y) { return Data[SizeX*y+x]; }
}

上面的代码允许您以方便的方式传递对此结构的引用。它只有6行代码!

当然,上面的代码需要更多的代码;例如,用于分配内存。但是,如果您仔细编写所有这些部件,那么使用它将非常安全,并且它应该受到良好的保护以防止错误。

答案 3 :(得分:2)

返回2D矢量不那么复杂。

#include <vector>
#include <iostream>
using namespace std;

typedef std::vector<std::vector< int> > vector2D;

int image[5][5] = 
{
     {0, 0, 0, 0, 0},
     {0, 1, 1, 1, 0},
     {0, 0, 1, 0, 0},
     {0, 1, 1, 1, 0},
     {0, 0, 1, 0, 0},
 };

int kernel[5][5] = 
{
     {0, 0, 0, 0, 0},
     {0, 1, 1, 1, 0},
     {0, 0, 1, 0, 0},
     {0, 1, 1, 1, 0},
     {0, 0, 1, 0, 0},
 };



vector2D  erode(int image[5][5], int kernel[5][5])
{
    vector2D image_process_data ;

    //create 2D vector array
    image_process_data.resize(5);
     for(int i = 0; i < 5; i++) 
     {
         image_process_data[i].resize(5);

     }

    //perform calculations
    for (int ix = 0; ix < 5; ix++)
    {
        for (int iy = 0; iy < 5; iy++)
        {
            image_process_data[ix][iy] = image[ix][iy] + kernel[ix][iy];

        }


    }        
    //return the 2D array
    return image_process_data;
}

int main( )
{
    vector2D new_image;

     new_image = erode(image, kernel);

    //display new_image
    for (int ix = 0; ix < 5; ix++)
    {
        for (int iy = 0; iy < 5; iy++)
        {
            cout<<new_image[ix][iy]<<" ";
        }
        cout<<"\n";

    }        



return 0;
}

如何设置2D矢量数组:

#include <vector>
#include <iostream>
using std namespace;

#define HEIGHT 5
#define WIDTH 3

int main() {
  vector<vector<double> > array2D;

  // Set up sizes. (HEIGHT x WIDTH)
  array2D.resize(HEIGHT);
  for (int i = 0; i < HEIGHT; ++i)
    array2D[i].resize(WIDTH);

  // Put some values in
  array2D[1][2] = 6.0;
  array2D[3][1] = 5.5;

  return 0;
}