2016-02-10 63 views
0

我有一个结构,根据用户在运行时的输入,它将需要一维数组或3D数组。它永远不会需要两者。现在,我已经像下面的示例代码中那样设置了它,其中单独的变量可以指向一维数组或3D数组。我想在结构中只有一个变量可以指向一维数组或维数在运行时设置的3D数组。我有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; 
    } 
} 
+3

'C/C++'是UB .. –

+2

我想你可能想用用C'new'(而不是'malloc')++。 – pzaenger

+0

所以标签以'C++'结尾 - 对我来说看起来更像'c'风格。 – 4386427

回答

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

+0

我接受了这个答案,因为它指向我重构我的代码的好方向。在实现类似的东西之前,我会花一些时间学习类和其他C++容器。谢谢! –

1

有关C/C++指针的多汁的事情之一是指针的存在。一个无效指针可以指向你想要的任何东西,从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; 
} 
+0

谢谢,这是很好的知道。但是,根据评论,看起来最好的答案将是对我的编码概念进行更为重大的修改。我会等待一个答案,告诉我如何清理我的代码,但如果没有出现,我会选择这个。 –