How can I use and emtpy 2-D array as a function argument?

What's up!..
Say, for example, I want to fill a 2D array with dots '.' to later print it
as a table or as a square whatever. something like this:

...
...
...

However I wan't to put it in a function so that I can later change the Width and Length of it. I also want to be able to access it later so that I can replace a dot with another character, kind of like a game, to later make that character move

...
.C.
...

But I just don't know how to pass a 2-D array as a function parameter. This is what I have for now:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  void Dungeon::createdungeon( char ar[][0], int width, int height )
{

    for( int i = 0; i < height; i++ )
    {
        for( int j = 0; j < width; j++ )
        {
            ar[i][j] = '.';
        }
    }
}

// Then in main:

int width = 8;
int height = 16;

char dungeon_board[height][width];

Dungeon testdungeon;
testdungeon.createboard( dungeon_board, width, height );


If i do this, however, it won't let me pass an array I create in main, or anywhere else for that matter, to the function.

I've tried with pointers, references and nothing works!..

Alright I think that wraps it up. Thank's for taking the time, you rock!..
You can use a double vector:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <vector>
using namespace std;

void print(vector<vector<char>> v) {
    for (size_t row = 0; row < v.size(); row++) {
        for (size_t col = 0; col < v[row].size(); col++)
            cout << v[row][col] << ' ';
        cout << '\n';
    }
    cout << '\n';
}

int main() {
    size_t height = 0, width = 0;
    cout << "height width: ";
    cin >> height >> width;

    vector<vector<char>> v(height, vector<char>(width, '.'));
    print(v);
    v[height/2][width/2] = 'X';
    print(v);
}


Or if you didn't want to use vectors:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <algorithm>
using namespace std;

char **new_matrix(size_t height, size_t width) {
    char **m = new char*[height];
    m[0] = new char[width * height];
    for (size_t i = 1; i < width; i++)
        m[i] = m[i - 1] + width;
    fill(&m[0][0], &m[height][0], '.');
    return m;
}

void print(char **m, size_t height, size_t width) {
    for (size_t row = 0; row < height; row++) {
        for (size_t col = 0; col < width; col++)
            cout << m[row][col] << ' ';
        cout << '\n';
    }
    cout << '\n';
}

int main() {
    size_t height = 0, width = 0;
    cout << "height width: ";
    cin >> height >> width;
    char **m = new_matrix(height, width);
    print(m, height, width);
    delete [] m[0];
    delete [] m;
}


And that can be wrapped in a class. May as well make the base type generic, too:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <algorithm>
using namespace std;

template <typename T>
class Matrix {
    size_t height, width;
    T** m;
public:
    Matrix(size_t height, size_t width);
    ~Matrix() { delete [] m[0]; delete [] m; }
    void print();
};

template <typename T>
Matrix<T>::Matrix(size_t height, size_t width)
    : height{height}, width{width} {
    m = new T*[height];
    m[0] = new T[width * height];
    for (size_t i = 1; i < width; i++)
        m[i] = m[i - 1] + width;
    fill(&m[0][0], &m[height][0], '.');
}

template <typename T>
void Matrix<T>::print() {
    for (size_t row = 0; row < height; row++) {
        for (size_t col = 0; col < width; col++)
            cout << m[row][col] << ' ';
        cout << '\n';
    }
    cout << '\n';
}

int main() {
    size_t height = 0, width = 0;
    cout << "height width: ";
    cin >> height >> width;

    Matrix<char> m(height, width);
    m.print();
}

Last edited on
so that I can later change the Width and Length of it

You should use vector of vectors. Pass to a function as a reference, or const reference (as in tpb's print example, which I'm sure he'll edit in soon ;D)
Last edited on
Thanks for your answers, appreciate it.
So basically, fuck 2-D arrays in this case right?
tpb went ham, awesome stuff man.
closed account (E0p9LyTq)
1D, 2D, 3D, run-time sizeable vectors are the way to go, vectors are easy to pass into functions without the need to pass the size of the container:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <vector>
#include <numeric>

template<typename T>
void Print2DArray(std::vector<std::vector<T>> const&);

int main()
{
   // creating a sized vector
   std::vector<int> aVec(5);
   std::cout << aVec.size() << '\n';

   for (size_t itr = 0; itr < aVec.size(); itr++)
   {
      std::cout << aVec[itr] << ' ';
   }
   std::cout << "\n\n";

   // creating a sized vector filled with a value other than zero
   std::vector<int> aVec2(5, 100);
   std::cout << aVec2.size() << '\n';

   for (auto& itr : aVec2)
   {
      std::cout << itr << ' ';
   }
   std::cout << "\n\n";

   std::cout << "Creating a 2-dimensional vector, enter row size: ";
   int row_size;
   std::cin >> row_size;

   std::cout << "Enter column size: ";
   int col_size;
   std::cin >> col_size;

   std::cout << "\n";

   // create a 2 dimensional int vector with known dimensions
   std::vector<std::vector<int>> aVector(row_size, std::vector<int>(col_size));

   // initialize the vector with some values other than zero
   int start  = 101;
   int offset = 100;

   for (auto& itr : aVector)
   {
      std::iota(itr.begin(), itr.end(), start);
      start += offset;
   }

   // let's display the filled 2D vector
   Print2DArray(aVector);
}


template<typename T>
void Print2DArray(std::vector<std::vector<T>> const& aVec)
{
   for (const auto& row_itr : aVec)
   {
      for (const auto& col_itr : row_itr)
      {
         std::cout << col_itr << ' ';
      }
      std::cout << '\n';
   }
}

5
0 0 0 0 0

5
100 100 100 100 100

Creating a 2-dimensional vector, enter row size: 3
Enter column size: 5

101 102 103 104 105
201 202 203 204 205
301 302 303 304 305

Creating vectors of known size(s) there is no need to push back values, the container is initialized on creation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <vector>

int main()
{
   std::cout << "Creating a 3-dimensional vector, enter depth size: ";
   int depth_size;
   std::cin >> depth_size;

   std::cout << "Enter row size: ";
   int row_size;
   std::cin >> row_size;

   std::cout << "Enter column size: ";
   int col_size;
   std::cin >> col_size;

   std::cout << "\n";

   // create a 3 dimensional int vector with known dimensions
   std::vector<std::vector<std::vector<int>>> aVector(depth_size, std::vector<std::vector<int>>(row_size, std::vector<int>(col_size, 0)));

   // let's display the initial 3D vector
   for (int depth_loop = 0; depth_loop < depth_size; depth_loop++)
   {
      for (int row_loop = 0; row_loop < row_size; row_loop++)
      {
         for (int col_loop = 0; col_loop < col_size; col_loop++)
         {
            // let's display the filled 2D vector
            std::cout << aVector[depth_loop][row_loop][col_loop] << ' ';
         }
         std::cout << '\n';
      }
      std::cout << '\n';
   }
   std::cout << '\n';

   // initialize the vector with some values
   for (int depth_loop = 0; depth_loop < depth_size; depth_loop++)
   {
      for (int row_loop = 0; row_loop < row_size; row_loop++)
      {
         for (int col_loop = 0; col_loop < col_size; col_loop++)
         {
            aVector[depth_loop][row_loop][col_loop] = (((depth_loop + 1) * 100) + ((row_loop + 1) * 10) + col_loop + 1);
         }
      }
   }

   // let's display the filled 3D vector
   for (int depth_loop = 0; depth_loop < depth_size; depth_loop++)
   {
      for (int row_loop = 0; row_loop < row_size; row_loop++)
      {
         for (int col_loop = 0; col_loop < col_size; col_loop++)
         {
            // let's display the filled 2D vector
            std::cout << aVector[depth_loop][row_loop][col_loop] << ' ';
         }
         std::cout << '\n';
      }
      std::cout << '\n';
   }
}

Creating a 3-dimensional vector, enter depth size: 3
Enter row size: 4
Enter column size: 5

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0


111 112 113 114 115
121 122 123 124 125
131 132 133 134 135
141 142 143 144 145

211 212 213 214 215
221 222 223 224 225
231 232 233 234 235
241 242 243 244 245

311 312 313 314 315
321 322 323 324 325
331 332 333 334 335
341 342 343 344 345
This allows printing 1D, 2D, or 3D vectors through ostream. Can the templates be condensed?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <vector>

template <typename T>
std::ostream& operator<<(std::ostream& os,
                         const std::vector<T>& v) {
    for (auto const& x: v) std::cout << x << ' ';
    return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os,
                         const std::vector<std::vector<T>>& v) {
    for (auto const& x: v) std::cout << x << '\n';
    return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os,
                         const std::vector<std::vector<std::vector<T>>>& v) {
    for (auto const& x: v) std::cout << x << '\n';
    return os;
}

int main()
{
   using std::cout;
   using std::cin;
   using std::vector;

   int depth, rows, cols;
   cout << "Creating a 3-dimensional vector.\n";
   cout << "Enter depth  rows  cols: ";
   cin >> depth >> rows >> cols;

   vector<vector<vector<int>>>  v (depth,
          vector<vector<int>>     (rows,
                 vector<int>      (cols)));

   cout << '\n' << v << '\n';

   for (int d = 0; d < depth; d++)
      for (int r = 0; r < rows; r++)
         for (int c = 0; c < cols; c++)
            v[d][r][c] = (d + 1) * 100 + (r + 1) * 10 + c + 1;

   cout << '\n' << v << '\n';
}

Last edited on
This is way more than I could've asked. Thanks a lot guys! Appreciate the time you took.
You rock!..
closed account (E0p9LyTq)
Can the templates be condensed?

Remove the third operator<< template. The second template will handle outputting both 2D & 3D vectors in a table format.

Vectors with more dimensions could be handled as well, but not in an easy to read table format.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <vector>

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
   for (auto const& x : v)
   {
      std::cout << x << ' ';
   }

   return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<T>>& v)
{
   for (auto const& x : v)
   {
      std::cout << x << '\n';
   }

   return os;
}

int main()
{
   std::cout << "Creating a 3-dimensional vector, enter depth size: ";
   int depth;
   std::cin >> depth;

   std::cout << "Enter row size: ";
   int row;
   std::cin >> row;

   std::cout << "Enter column size: ";
   int col;
   std::cin >> col;

   std::cout << "\n";

   using std::vector;

   // create a 3 dimensional int vector with known dimensions
   vector<vector<vector<int>>> aVec(depth, vector<vector<int>>(row, vector<int>(col, 0)));

   // let's display the initial 3D vector
   std::cout << aVec << '\n';

   // initialize the vector with some values
   for (int depth_loop = 0; depth_loop < depth; depth_loop++)
   {
      for (int row_loop = 0; row_loop < row; row_loop++)
      {
         for (int col_loop = 0; col_loop < col; col_loop++)
         {
            aVec[depth_loop][row_loop][col_loop] = (((depth_loop + 1) * 100)
                                                    + ((row_loop + 1) * 10) + col_loop + 1);
         }
      }
   }

   // let's display the filled 3D vector
   std::cout << aVec;
}

Creating a 3-dimensional vector, enter depth size: 3
Enter row size: 4
Enter column size: 5

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0


111 112 113 114 115
121 122 123 124 125
131 132 133 134 135
141 142 143 144 145

211 212 213 214 215
221 222 223 224 225
231 232 233 234 235
241 242 243 244 245

311 312 313 314 315
321 322 323 324 325
331 332 333 334 335
341 342 343 344 345
Thanks FG. I knew I was missing something.
Your initialization can be written similarly.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <vector>

template <typename T>
std::ostream& operator<<(std::ostream& os,
                         const std::vector<T>& v) {
    for (auto const& x: v) std::cout << x << ' ';
    return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os,
                         const std::vector<std::vector<T>>& v) {
    for (auto const& x: v) std::cout << x << '\n';
    return os;
}

void init(std::vector<int>& v, int lo = 0, int n = 0) {
    int i = lo;
    for (auto &x: v) x = n * 10 + i++;
}

template <typename T>
void init(std::vector<std::vector<T>>& v, int lo = 0, int n = 0) {
    int i = lo;
    for (auto &x: v) init(x, lo, n * 10 + i++);
}

int main() {
    using std::cout;
    using std::cin;
    using std::vector;

    int depth, rows, cols;
    cout << "Enter depth rows cols: ";
    cin >> depth >> rows >> cols;

    vector<vector<vector<int>>> v (depth,
           vector<vector<int>>    (rows,
                  vector<int>     (cols)));
    init(v, 1);
    cout << "\nv:\n" << v << '\n';

    vector<vector<int>> w (rows * 2,
           vector<int>    (cols * 2));
    init(w, 1);
    cout << "w:\n" << w << '\n';

    vector<int> x (rows * 3);
    init(x, 1);
    cout << "x:\n" << x << '\n';
}


Enter depth rows cols: 3 4 5

v:
111 112 113 114 115 
121 122 123 124 125 
131 132 133 134 135 
141 142 143 144 145 

211 212 213 214 215 
221 222 223 224 225 
231 232 233 234 235 
241 242 243 244 245 

311 312 313 314 315 
321 322 323 324 325 
331 332 333 334 335 
341 342 343 344 345 


w:
11 12 13 14 15 16 17 18 19 20 
21 22 23 24 25 26 27 28 29 30 
31 32 33 34 35 36 37 38 39 40 
41 42 43 44 45 46 47 48 49 50 
51 52 53 54 55 56 57 58 59 60 
61 62 63 64 65 66 67 68 69 70 
71 72 73 74 75 76 77 78 79 80 
81 82 83 84 85 86 87 88 89 90 

x:
1 2 3 4 5 6 7 8 9 10 11 12 


It would be possible to write just one operator<< template if you could tell if T was a non-vector.
Last edited on
closed account (E0p9LyTq)
tpb wrote:
It would be possible to write just one operator<< template if you could tell if T was a non-vector.
Is that kind of thing possible?

Maybe using the type_info on the passed object?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <typeinfo> // operator typeid
#include <vector>
#include <string>

int main()
{
   std::vector<std::vector<int>> v(3, std::vector<int>(4));

   std::string s1 = typeid(v).name();
   std::string s2 = typeid(v[0]).name();

   std::cout << s1 << "\n\n" << s2 << "\n\n";

   using std::vector;
   vector<vector<vector<int>>> v2(3, vector<vector<int>>(4, vector<int>(5, 0)));

   s1 = typeid(v2).name();
   s2 = typeid(v2[0]).name();
   std::string s3 = typeid(v2[0][0]).name();

   std::cout << s1 << "\n\n" << s2 << "\n\n" << s3 << '\n';
}
Topic archived. No new replies allowed.