在运行时设置数组维度

时间:2016-02-10 17:51:11

标签: c++ arrays multidimensional-array struct

我有一个结构,根据运行时的用户输入,它将需要一维数组或三维数组。它永远不需要两者兼得。现在,我在下面的示例代码中进行了设置,使用可以指向一维数组或三维数组的单独变量。我想在结构中只有一个可以指向一维数组或三维数组的变量,其中维度是在运行时设置的。我有C的中级知识,并且是C ++的初学者。我愿意接受基于C ++概念的答案,但如果没有减速(或可忽略不计的减速),则与迭代值时使用C相比。如果它是一个3D数组,那么访问和更改数组值的for循环是我的代码中最大的瓶颈。一旦设置了阵列,我就不需要改变阵列的尺寸或大小了。

有没有办法做到这一点,或者我应该满足于在我的结构中总是有一个无关的变量?

#include <iostream>
using namespace std;

typedef struct {
  int dim;
  int *one_d_arr;
  int ***three_d_arr;
} Struct;

int main() {
  int count = 0;
  int *arr1 = (int*) malloc(2 * sizeof(int));
  arr1[0] = 0;
  arr1[1] = 1;
  int ***arr3 = (int***) malloc(2 * sizeof(int**));
  for (int i=0; i<2; i++) {
    arr3[i] = (int**) malloc(2 * sizeof(int*));
    for (int j=0; j<2; j++) {
      arr3[i][j] = (int*) malloc(2 * sizeof(int));
      for (int k=0; k<2; k++) {
        arr3[i][j][k] = count++;
      }   
    }   
  }
  Struct s;
  s.one_d_arr = NULL;
  s.three_d_arr = NULL;
  cout << "Enter number of dimensions: ";
  cin >> s.dim;
  if (s.dim==1) {
    s.one_d_arr = arr1;
    cout << s.one_d_arr[0] << ", " << s.one_d_arr[1] << endl;
  }
  else if (s.dim==3) {
    s.three_d_arr = arr3;
    cout << s.three_d_arr[0][0][0] << ", " << s.three_d_arr[0][0][1] << endl;
    cout << s.three_d_arr[0][1][0] << ", " << s.three_d_arr[0][1][1] << endl;
    cout << s.three_d_arr[1][0][0] << ", " << s.three_d_arr[1][0][1] << endl;
    cout << s.three_d_arr[1][1][0] << ", " << s.three_d_arr[1][1][1] << endl;
  }
  else {
    cout << "Must enter 1 or 3" << endl;
  }
}

2 个答案:

答案 0 :(得分:1)

我的建议是在这里使用两种不同的类型,而不是单个结构。使用抽象基类,可以使两个子类符合单个接口,但它们具有不同的基础行为。一个非常基本的例子:

class ArrayBase {
  int dim;

  public:
    // This function is pure virtual, which means it's impossible to      
    // instantiate an instance of ArrayBase. Any class that inherits from
    // ArrayBase must implement printArray().
    virtual void printArray() = 0;
}

class Array1D : public ArrayBase {
  int* array;

  void printArray() {
    // some code to print this one-dimensional array
  }
}

class Array3D : public ArrayBase {
  int*** array;

  void printArray() {
    // some code to print this three-dimensional array
  }
}

稍后,当您需要使用该数组时,您可以动态分配所需的类型,如下所示:

ArrayBase* inputArray;

// if the user wants a 1D array
inputArray = new Array1D();

// if the user wants a 3D array
inputArray = new Array3D();

// this will call the appropriate function to print the array
inputArray->printArray(); 

如果你真的想拥有一个类型,使用boost :: any是将两个数组指针压缩成一个的一种方法。我不推荐这种方法,但它会起作用。

答案 1 :(得分:1)

关于C / C ++指针的一个有趣的事情是存在 void 指针。 void 指针可以指向您想要的任何内容,从 int int ***。 所以你可以简单地使用以下代码:

#define CAST1(arr) ((int *)arr)
#define CAST3(arr) ((int ***)arr)
#define CAST(arr,i) CAST##i(arr)

typedef struct {
    int dim;
    void *arr;
} Struct;

int main()
{
    Struct s;
    cin >> s.dim;
    int count = 0;

if (s.dim == 1){
    s.arr = malloc(2 * sizeof(int));
    CAST(s.arr, 1)[0] = 0;
    CAST(s.arr, 1)[1] = 1;
}
else if (s.dim == 3){
    s.arr = malloc(2 * sizeof(int ***));
    for (int i = 0; i < 2; i++){
        CAST(s.arr, 3)[i] = (int **) malloc(2 * sizeof(int **));
        for (int j = 0; j < 2; j++){
            CAST(s.arr, 3)[i][j] = (int *)malloc(2 * sizeof(int *));
            for (int k = 0; k < 2; k++){
                CAST(s.arr, 3)[i][j][k] = count++;
            }
        }
    }
}

if (s.dim == 1) {
    cout << CAST(s.arr, 1)[0] << ", " << CAST(s.arr, 1)[1] << endl;
}
else if (s.dim == 3) {
    cout << CAST(s.arr, 3)[0][0][0] << ", " << CAST(s.arr, 3)[0][0][1] << endl;
    cout << CAST(s.arr, 3)[0][1][0] << ", " << CAST(s.arr, 3)[0][1][1] << endl;
    cout << CAST(s.arr, 3)[1][0][0] << ", " << CAST(s.arr, 3)[1][0][1] << endl;
    cout << CAST(s.arr, 3)[1][1][0] << ", " << CAST(s.arr, 3)[1][1][1] << endl;
}
else {
    cout << "Must enter 1 or 3" << endl;
}

system("pause");

return 0;
}