在运行时设置数组维度

Set array dimension at runtime

本文关键字:数组 设置 运行时      更新时间:2023-10-16

我有一个结构,根据用户在运行时的输入,它要么需要一个一维数组,要么需要一个三维数组。它永远不会需要两者兼而有之。现在,我按照下面的示例代码进行了设置,其中包含可以指向 1D 数组或 3D 数组的单独变量。我只想在结构中有一个变量,可以指向 1D 数组或 3D 数组,其中维度是在运行时设置的。我有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;
  }
}

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

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 是将两个数组指针压缩为一个的一种方法。我不推荐这种方法,但它会起作用。

关于 C/C++ 指针的一个多汁的事情是存在空指针。void 指针可以指向您想要的任何内容,从 intint ***。因此,您可以简单地使用以下代码:

#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;
}