0

How to declare a 2D array in which the rows are dynamic but the rows length are fixed? Is there any way to do it without both row and rows length are dynamic?

P.S. I can't use STL containers or class string.

1

4 Answers 4

4

You can use std::vector and std::array for this.

std::vector is a dynamic-length array.

std::array is a fixed-length array, used as

array<int, 20> arr;
arr[10] = 42;
array<int, 20> anotherArr = arr; // copied here, as opposed to C arrays

int oldStyleArr[20];
oldStyleArr[10] = 42;
// int newStyleArr[20] = oldStyleArr; // error here

It is a convenient wrapper over the C-style array, and it provides value semantics and various conveniece methods like size().

So you can create array<vector<int>, 20> for an array of 20 dynamic vectors of ints or vector<array<int, 20>> for a dynamic vector of fixed-length arrays.

UPD: std::array works only with array bounds known at compile-time. If your array bounds are known only at runtime, you still can use std::vector's constructor from size and (optional) element:

int rowCount, columnCount;
cin >> rowCount >> columnCount;
using Row = vector<int>;

// create `vector` of `rowCount` rows,
// where each row is `vector` of `columnCount` ints
vector<Row> arr2d(rowCount, Row(columnCount));

However, that's not the most efficient solution because each row is allocated separately. You can solve this with a little wrapper over one-dimensional vector:

template<class T>
class Vector2D {
public:
  Vector2D(int rows, int cols)
    : data(rows*cols)
    , rows(rows)
    , cols(cols) {}

  int rowCount() const { return rows; }
  int columnCount() const { return cols; }

  T&       get(int r, int c)       { return data[r*cols + c]; }
  T const& get(int r, int c) const { return data[r*cols + c]; }

  void addRow() {
    data.resize(cols*(rows + 1));
  }

// ...

private:
  vector<T> data;
  int rows;
  int cols;
};
2
  • This works if the width is known at compile type. But it won't work for a real 2D array with rows and columns only known at runtime
    – phuclv
    Commented Apr 19, 2020 at 10:20
  • @phuclv Dynamic arrays like vectors will perfectly fit in this case Commented Apr 19, 2020 at 18:25
0

You can use std::vector for dynamic range arrays. You would want to instantiate a vector of arrays to achieve this.

2
  • 3
    you mean std::vector (without uppercase). I think you have to explain more for the OP, also given example
    – bruno
    Commented Apr 19, 2020 at 9:37
  • 1
    You are right, that was a bit short. Yuri already gave a more extensive answer so I won't duplicate it but I will try to do better next time.
    – Cerenia
    Commented Apr 19, 2020 at 9:50
0

What you are looking for is probably: std::vector<std::array<int, 20>> arr;

However, if STL containers are not an option you might need to implement the container yourself. A linked list is probably the easiest to implement.

0

Just declare a 1D array and calculate the index yourself like how compilers generate accesses to a multidimensional array. Each row has width items, so the [x][y] element will have the index x*width + y

template<typename T>
class twoD
{
    const int width;
    const int height;
    T* data;

    twoD(int w, int h) : width(w), height(h)
    {
        data = new T[width*height];
    }

    ~twoD()
    {
        delete[] data;
    }

    T& at(int x, int y)
    {
        return data[x*width + y];
    }

    T const& at(int x, int y) const
    {
        return data[x*width + y];
    }
}

twoD myArray(4, 8);
myArray.at(2, 3) = 5;
myArray.at(4, 5) = 6 - myArray.at(2, 3);

The same method can be used to access multidimensional arrays in any degree

1
  • @Strick it's only a very simple example and not a full-blown solution. I'm not solving everything in OP's likely homework
    – phuclv
    Commented Apr 19, 2020 at 10:21

Not the answer you're looking for? Browse other questions tagged or ask your own question.