3D-массив С++ с использованием оператора int []

Я новичок в C/С++, и я взломал голову, но до сих пор не знаю, как создать "структуру", подобную этой

alt text

Он должен быть трехмерным динамическим массивом с помощью указателей.

Я начал так, но застрял там

  int x=5,y=4,z=3;
  int ***sec=new int **[x];

Достаточно было бы знать, как сделать это для статического размера y и z;

Пожалуйста, я был бы признателен, что вы мне поможете.

Спасибо заранее.

Ответы

Ответ 1

Чтобы создать динамически 3D массив целых чисел, лучше сначала понять 1D и 2D-массив.

1D массив: вы можете сделать это очень легко

const int MAX_SIZE=128;
int *arr1D = new int[MAX_SIZE];

Здесь мы создаем int-pointer, который укажет на кусок памяти, где целые числа могут быть сохранены.

2D-массив. Вы можете использовать решение выше 1D-массива для создания 2D-массива. Сначала создайте указатель, который должен указывать на блок памяти, где хранятся только другие целые указатели, которые в конечном счете указывают на фактические данные. Поскольку наш первый указатель указывает на массив указателей, поэтому он будет вызываться как указатель на указатель (двойной указатель).

const int HEIGHT=20;
const int WIDTH=20;

int **arr2D = new int*[WIDTH];  //create an array of int pointers (int*), that will point to 
                                //data as described in 1D array.
for(int i = 0;i < WIDTH; i++){
      arr2D[i] = new int[HEIGHT]; 
}

3D-массив. Это то, что вы хотите сделать. Здесь вы можете попробовать как схему, используемую в двух предыдущих случаях. Примените ту же логику, что и 2D-массив. Диаграмма, о которой идет речь, объясняет все. Первый массив будет указателем на указатель на указатель (int *** - поскольку он указывает на двойные указатели). Решение выглядит следующим образом:

const int X=20;
const int Y=20;
const int z=20;

int ***arr3D = new int**[X];
for(int i =0; i<X; i++){
   arr3D[i] = new int*[Y];
   for(int j =0; j<Y; j++){
       arr3D[i][j] = new int[Z];
       for(int k = 0; k<Z;k++){
          arr3D[i][j][k] = 0;
       }
   }
}

Ответ 2

// one-liner
typedef std::vector<std::vector<std::vector<int> > > ThreeDimensions;
// expanded
typedef std::vector<int> OneDimension;
typedef std::vector<OneDimension> TwoDimensions;
typedef std::vector<TwoDimension> ThreeDimensions;

(в конце концов, это помечено как С++)

EDIT в ответ на вопрос Джо

привет снова Джо =) уверен. вот пример:

#include <vector>
#include <iostream>

int main(int argc, char* const argv[]) {

    /* one-liner */
    typedef std::vector<std::vector<std::vector<int> > >ThreeDimensions;
    /* expanded */
    typedef std::vector<int>OneDimension;
    typedef std::vector<OneDimension>TwoDimensions;
    typedef std::vector<TwoDimensions>ThreeDimensions;

    /*
       create 3 * 10 * 25 array filled with '12'
     */
    const size_t NElements1(25);
    const size_t NElements2(10);
    const size_t NElements3(3);
    const int InitialValueForAllEntries(12);

    ThreeDimensions three_dim(NElements3, TwoDimensions(NElements2, OneDimension(NElements1, InitialValueForAllEntries)));

    /* the easiest way to assign a value is to use the subscript operator */
    three_dim[0][0][0] = 11;
    /* now read the value: */
    std::cout << "It should be 11: " << three_dim[0][0][0] << "\n";
    /* every other value should be 12: */
    std::cout << "It should be 12: " << three_dim[0][1][0] << "\n";

    /* get a reference to a 2d vector: */
    TwoDimensions& two_dim(three_dim[1]);

    /* assignment */
    two_dim[2][4] = -1;
    /* read it: */
    std::cout << "It should be -1: " << two_dim[2][4] << "\n";

    /* get a reference to a 1d vector: */
    OneDimension& one_dim(two_dim[2]);

    /* read it (this is two_dim[2][4], aka three_dim[1][2][4]): */
    std::cout << "It should be -1: " << one_dim[4] << "\n";
    /* you can also use at(size_t): */
    std::cout << "It should be 12: " << one_dim.at(5) << "\n";

    return 0;
}

Ответ 3

Вы можете попробовать:

for(int i=0;i<x;i++) {
  sec[i] = new int *[y];
  for(int j=0;j<y;j++) {
    sec[i][j] = new int [z];
  }
}

И как только вы закончите использовать эту память, вы можете освободить ее как:

for(int i=0;i<x;i++) {
  for(int j=0;j<y;j++) {
    delete [] sec[i][j];
  }
  delete [] sec[i];
}
delete [] sec;

Ответ 4

Комплексные ответы.

Если вы действительно пишете это на С++ (не грубо C), я думаю, вам стоит взглянуть на эту сложную структуру данных. Редизайн IMO, учитывая то, что вы пытаетесь сделать, будет лучше.

Ответ 5

То, что вы пытаетесь сделать, не является идиоматическим в С++. Конечно, для этого вы можете использовать int***pointer, но это настоятельно не рекомендуется. В С++ у нас есть лучшие способы добраться туда.

vector<vector<vector<int> > > foo (5,vector<vector<int> >(4, vector<int>(3)));

Это приведет к чему-то, с расположением памяти, аналогичным тому, что вы просили. Он поддерживает динамическое изменение размера и внутренние векторы, чтобы иметь разные размеры, как на картинке. Кроме того, вам не нужно беспокоиться о ручном распределении/удалении любого из них. Кроме того, векторы знают свой размер, поэтому вам не нужно его где-то помнить.

Но если вы просто хотите "прямоугольный" 3D-массив, где все элементы последовательно хранятся в одном блоке памяти, вы можете использовать boost:: multiarray.

Ответ 6

OK давайте начнем ваши начинания

int ***sec = new int**[x]; 

sec теперь является массивом int ** s длины x, поэтому теперь я собираюсь сосредоточиться на том, чтобы сделать элемент zeroeth тем, что вы хотите

sec[0] = new int*[y];

Теперь sec [0] указывает на массив int * s длины y, теперь просто нужно получить последний бит дерева, поэтому

sec[0][0] = new int[z];

И наконец, чтобы получить его в форме на диаграмме

sec[0][0][z-1] = 0;

Это похоже на вопрос о домашнем задании, убедитесь, что вы действительно понимаете ответ и почему он работает.