By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,948 Members | 804 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,948 IT Pros & Developers. It's quick & easy.

passing a 2d array as a paramater

P: n/a
Is there a way to pass a 2d array to a function in c++ with out having
to specifiy the number of elements in the array. Here is an example

Expand|Select|Wrap|Line Numbers
  1. #include<iostream>
  2. using namespace std;
  3.  
  4. int main()
  5. {
  6. int array[10][10];
  7. fill(array,rows,cols);
  8. return 0;
  9.  
  10. }
  11. void fill(int array[10][10], rows,cols)
  12. {
  13. int i, j;
  14.  
  15. for(i=0;i<10;i++)
  16. for(j=0;j<10;j++)
  17. array[i][j]=0;
  18. }
  19.  
array needs to have the [10][10] or at least
[][10]. is there a way i can make it so it
only needs [][]?

Aug 27 '05 #1
Share this Question
Share on Google+
18 Replies


P: n/a
la******@yahoo.com wrote:
Is there a way to pass a 2d array to a function in c++ with out having
to specifiy the number of elements in the array. Here is an example

Expand|Select|Wrap|Line Numbers
  1.  #include<iostream>
  2.  using namespace std;
  3.  int main()
  4.  {
  5.     int array[10][10];
  6.     fill(array,rows,cols);
  7.     return 0;
  8.  }
  9.  void fill(int array[10][10], rows,cols)
  10.  {
  11.     int i, j;
  12.     for(i=0;i<10;i++)
  13.     for(j=0;j<10;j++)
  14.     array[i][j]=0;
  15.  }
  16.  
array needs to have the [10][10] or at least
[][10]. is there a way i can make it so it
only needs [][]?


I could be wrong, but I think no. This is because the compiler can't do
math on the pointer without knowing the secondary dimensions.

--John Ratliff
Aug 27 '05 #2

P: n/a
la******@yahoo.com wrote:
Is there a way to pass a 2d array to a function in c++ with out having
to specifiy the number of elements in the array. Here is an example

Expand|Select|Wrap|Line Numbers
  1.  #include<iostream>
  2.  using namespace std;
  3.  int main()
  4.  {
  5.     int array[10][10];
  6.     fill(array,rows,cols);
  7.     return 0;
  8.  }
  9.  void fill(int array[10][10], rows,cols)
  10.  {
  11.     int i, j;
  12.     for(i=0;i<10;i++)
  13.     for(j=0;j<10;j++)
  14.     array[i][j]=0;
  15.  }
  16.  
array needs to have the [10][10] or at least
[][10]. is there a way i can make it so it
only needs [][]?
You could consider

a) packaging your matrix into a class.
b) turning that class into a template.

a) has the advantage that it separates the implementation from the
interface.

b) makes the whole thing more generic.

E.g.:

template < typename arithmetic_type, unsigned long ROWS, unsigned long COLS class matrix {
public:

typedef arithmetic_type value_type;

static
const unsigned long rows = ROWS;

static
const unsigned long cols = COLS;

private:

value_type data [ rows ][cols];

public:

value_type & operator() ( unsigned long row_index,
unsigned long col_index ) {
return( data[row_index][col_index] );
}

value_type const & operator() ( unsigned long row_index,
unsigned long col_index ) const {
return( data[row_index][col_index] );
}
};// matrix

template < typename arithmetic_type, unsigned long ROWS, unsigned long COLS

void fill_matrix ( matrix< arithmetic_type, ROWS, COLS > & matr ) {
for ( unsigned long r = 0; r < ROWS; ++r ) {
for ( unsigned long c = 0; c < COLS; ++c ) {
matr(r,c) = 0;
}
}
}

typedef matrix< float, 3001, 204 > MediumMatrix;

int main ( void ) {
MediumMatrix mat;
fill_matrix( mat );
}
Note in particular, how template resolution allows you to not explicitly
pass the dimensions of mat to the function fill_matrix(). The static type
of the object mat is all that the compiler needs to choose the right
dimensions.
Best

Kai-Uwe Bux
Aug 27 '05 #3

P: n/a
<la******@yahoo.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com...
Is there a way to pass a 2d array to a function in c++ with out having
to specifiy the number of elements in the array. Here is an example

Expand|Select|Wrap|Line Numbers
  1.  #include<iostream>
  2.  using namespace std;
  3.  int main()
  4.  {
  5.     int array[10][10];
  6.     fill(array,rows,cols);
  7.     return 0;
  8.  }
  9.  void fill(int array[10][10], rows,cols)
  10.  {
  11.     int i, j;
  12.     for(i=0;i<10;i++)
  13.     for(j=0;j<10;j++)
  14.     array[i][j]=0;
  15.  }
  16.  
array needs to have the [10][10] or at least
[][10]. is there a way i can make it so it
only needs [][]?


One solution is given in the C FAQ here:

http://www.eskimo.com/~scs/C-faq/q6.19.html

This solution is covered in Stroustrup's TC++PL.

--
David Hilsee
Aug 27 '05 #4

P: n/a
Kai_Uwe Bux, The disadvantage of having to write a new class for 2D,
3D, 4D etc matrices can be ameriolated by using the boost:multi_array
template class:

int rows(1000);
int columns(1000);

//num_dimensions = 2
boost::multi_array< int , 2 > foo( boost::extents[rows][columns] ); //2
= two dimentions

and your fill function fill(foo&) body might look like

for ( unsigned long r = 0; r < ROWS; ++r ) {
for ( unsigned long c = 0; c < COLS; ++c ) {
foo[r][c] = 0.0;
}
}

Aug 27 '05 #5

P: n/a
Frank Chang wrote:
Kai_Uwe Bux, The disadvantage of having to write a new class for 2D,
3D, 4D etc matrices can be ameriolated by using the boost:multi_array
template class:
Frank Chang,

a) we do not know if the OP wants to go into 3D and 4D.

b) in any case, one sure does not "have to write a new class". As was
pointed out to the OP in another thread already, there are libraries for
linear algebras, even free ones. You pointed toward the Boost matrix
library yourself, if I recall correctly. However, for some reason the OP
does not seem to be at ease with the idea of using third party libraries.

Thus, I was merely pointing out that there is an advantage in encapsulation.

int rows(1000);
int columns(1000);

//num_dimensions = 2
boost::multi_array< int , 2 > foo( boost::extents[rows][columns] ); //2
= two dimentions

and your fill function fill(foo&) body might look like

for ( unsigned long r = 0; r < ROWS; ++r ) {
for ( unsigned long c = 0; c < COLS; ++c ) {
foo[r][c] = 0.0;
}
}


Yup, that's cool. Now, sell that to the OP -- need to convince me.
Best

Kai-Uwe Bux
Aug 27 '05 #6

P: n/a
Kai-Uwe Bux, I understand that the original poster's question dealt
with 2D arrays. But, in engineering and science C++ applications, one
sometimes needs to abstract solutions to N dimensional solutions. That
way, the solution is more extensible to other problems.

I know we talked about the boost::Matrix class, which is only a 2
dimensional matrix, before but the OP in this case still wants to deal
with two dimensional arrays rather than matrix classes using the
vector-of-vector paridigm which you developed. What can we do? The OP
states:
"Is there a way to pass a 2d array to a function in c++ with out having

to specifiy the number of elements in the array"

In conclusion, your solution appears to be correct for the OP's problem
and I am not going to dispute you on that. Thank you for your reply.

Aug 27 '05 #7

P: n/a

la******@yahoo.com wrote:
Is there a way to pass a 2d array to a function in c++ with out having
to specifiy the number of elements in the array. Here is an example

Expand|Select|Wrap|Line Numbers
  1.  #include<iostream>
  2.  using namespace std;
  3.  int main()
  4.  {
  5.     int array[10][10];
  6.     fill(array,rows,cols);
  7.     return 0;
  8.  }
  9.  void fill(int array[10][10], rows,cols)
  10.  {
  11.     int i, j;
  12.     for(i=0;i<10;i++)
  13.     for(j=0;j<10;j++)
  14.     array[i][j]=0;
  15.  }
  16.  
array needs to have the [10][10] or at least
[][10]. is there a way i can make it so it
only needs [][]?


maybe

template<unsigned rows,unsigned cols>
void fill(int (&array)[rows][cols])

?

Aug 29 '05 #8

P: n/a
Aleksey, You could make your template even more generic;

template<typename T, unsigned rows,unsigned cols>
void fill(T (&array)[rows][cols])
{
int i, j;

for(i=0;i<10;i++)
for(j=0;j<10;j++)
array[i][j]=0;
}
int _tmain(int argc, _TCHAR* argv[])
{
Complex array[10][10];
fill<Complex>(array);
}

Aug 29 '05 #9

P: n/a
On 29 Aug 2005 03:53:29 -0700, "Frank Chang" <Fr**********@gmail.com> wrote:
Aleksey, You could make your template even more generic;

template<typename T, unsigned rows,unsigned cols>
void fill(T (&array)[rows][cols])
{
int i, j;

for(i=0;i<10;i++)
for(j=0;j<10;j++)
array[i][j]=0;
}
int _tmain(int argc, _TCHAR* argv[])
{
Complex array[10][10];
fill<Complex>(array);
}


Or even better,

#include <vector>

using namespace std;

typedef vector<vector<int>> vvi_t;

void fill(vvi_t& array)
{
array.reserve(10);
for (int i = 0; i < 10; ++i) {
array[i].reserve(10);
for (int j = 0; j < 10; ++i) {
array[i][j] = 0;
}
}
}

....
Aug 30 '05 #10

P: n/a
"Dave Rahardja" <as*@me.com> wrote in message
news:0j********************************@4ax.com...
On 29 Aug 2005 03:53:29 -0700, "Frank Chang" <Fr**********@gmail.com> wrote:
Aleksey, You could make your template even more generic;

template<typename T, unsigned rows,unsigned cols>
void fill(T (&array)[rows][cols])
{
int i, j;

for(i=0;i<10;i++)
for(j=0;j<10;j++)
array[i][j]=0;
}
int _tmain(int argc, _TCHAR* argv[])
{
Complex array[10][10];
fill<Complex>(array);
}


Or even better,

#include <vector>

using namespace std;

typedef vector<vector<int>> vvi_t;

void fill(vvi_t& array)
{
array.reserve(10);
for (int i = 0; i < 10; ++i) {
array[i].reserve(10);
for (int j = 0; j < 10; ++i) {
array[i][j] = 0;
}
}
}


While std::vector is generally better and more powerful than an array, this
code isn't as generic as Frank's and also has bugs because it uses reserve()
instead of resize() (the assignment to zero would be unnecessary with
resize() as well). It also does not allow the calling code to provide the
dimensions, but that's a nitpick.

--
David Hilsee
Aug 30 '05 #11

P: n/a

Frank Chang wrote:
Aleksey, You could make your template even more generic;
:) i know :)
add sugar, if you like...

template<typename T, unsigned rows,unsigned cols>
void fill(T (&array)[rows][cols])
{
}
int _tmain(int argc, _TCHAR* argv[])
what is _tmain()? :)
{
Complex array[10][10];
fill<Complex>(array);
complex doesn't needed here
}


Aug 30 '05 #12

P: n/a
On Mon, 29 Aug 2005 21:57:42 -0400, "David Hilsee" <da*************@yahoo.com>
wrote:
"Dave Rahardja" <as*@me.com> wrote in message
news:0j********************************@4ax.com.. .
On 29 Aug 2005 03:53:29 -0700, "Frank Chang" <Fr**********@gmail.com>

wrote:
>Aleksey, You could make your template even more generic;
>
>template<typename T, unsigned rows,unsigned cols>
>void fill(T (&array)[rows][cols])
>{
> int i, j;
>
> for(i=0;i<10;i++)
> for(j=0;j<10;j++)
> array[i][j]=0;
>}
>
>
>int _tmain(int argc, _TCHAR* argv[])
>{
> Complex array[10][10];
> fill<Complex>(array);
>}


Or even better,

#include <vector>

using namespace std;

typedef vector<vector<int>> vvi_t;

void fill(vvi_t& array)
{
array.reserve(10);
for (int i = 0; i < 10; ++i) {
array[i].reserve(10);
for (int j = 0; j < 10; ++i) {
array[i][j] = 0;
}
}
}


While std::vector is generally better and more powerful than an array, this
code isn't as generic as Frank's and also has bugs because it uses reserve()
instead of resize() (the assignment to zero would be unnecessary with
resize() as well). It also does not allow the calling code to provide the
dimensions, but that's a nitpick.


Oops, you are correct about reserve(). It should have been

if (array.size() < 10) array.resize(10);

or something like that.

This may be a moot point, but I thought the OP wanted to fill the first 10
elements of the array (in both dimensions) with zeros, regardless of the
actual size of the array. Anyway, add features to taste, I suppose.
Aug 30 '05 #13

P: n/a
la******@yahoo.com wrote:
Is there a way to pass a 2d array to a function in c++ with out having
to specifiy the number of elements in the array. Here is an example cat fill.c #include <stdlib.h>

void
fill(size_t rows, size_t cols, int array[rows][cols], int k) {
for (size_t i = 0; i < rows; ++i)
for (size_t j = 0; j < cols; ++j)
array[i][j] = k;
}
gcc -Wall -std=c99 -pedantic -c fill.c
cat main.cc #include<iostream>

extern "C" {
void fill(size_t, size_t, int*, int);
}

int main(int argc, char* argv) {
const size_t rows = 10;
const size_t cols = 10;
int array[rows][cols];

fill(rows, cols, &array[0][0], 0);
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < cols; ++j)
std::cout << ' ' << array[i][j];
std::cout << std::endl;
}

return 0;
}
g++ -Wall -ansi -pedantic -o main main.cc fill.o
./main

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
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

Eventually, C++ will adopt C99 variable size arrays
and you will be able to compile fill with your C++ compiler.
Aug 30 '05 #14

P: n/a
Aleksey, _tmain() is the MSVC 7.1 version of the main function
automatically generated when you create a new MSVC 7.1 program.
Regarding complex, the reason I put it there was because the original
poster has been talking about a two dimensional array of complex
numbers in other posts and I was just trying to show the syntatic sugar
..
The other issue I would like to raise is this:
template<unsigned rows,unsigned cols>
void fill(int (&array)[rows][cols])


What would you think about using an non-template fill function without
specifying template arguments for the number of rows and columns? For
example,

typedef boost::multi_array<int,2> marray; // 2 dimensional

void fill_matrix(marray& matr)
{
// we can deduce the rows and columns of the matrix matr
// by using boost multi_array member functions instead
// of template arguments.

multi_array< int, 2 >::iterator it = matr.begin();
// use iterator it to fill matr with 0's
}
int _tmain(int argc, _TCHAR* argv[])
{
using namespace boost;
using namespace std;

boost::multi_array< int , 2 > matr(boost::extents[10][12]); //10
rows, 12 cols
fill_matrix(matr);
}

If this program runs okay for you, then we are no longer debating about
syntatic sugar. Please take a look at www.boost.org for more
information if you should wish. Thank you.

Aug 31 '05 #15

P: n/a

Frank Chang wrote:
Aleksey, _tmain() is the MSVC 7.1 version of the main function
automatically generated when you create a new MSVC 7.1 program.
non standard
Regarding complex, the reason I put it there was because the original
poster has been talking about a two dimensional array of complex
numbers in other posts and I was just trying to show the syntatic sugar.
i mean that you don't need to type explicit fintion name like
"fill<complex>"...
The other issue I would like to raise is this:
template<unsigned rows,unsigned cols>
void fill(int (&array)[rows][cols])


here i just show OP way to pass multidimensional array to the function.
What would you think about using an non-template fill function without
specifying template arguments for the number of rows and columns? For
example,

for small programs arrays will enough, i think

typedef boost::multi_array<int,2> marray; // 2 dimensional

void fill_matrix(marray& matr)
{
// we can deduce the rows and columns of the matrix matr
// by using boost multi_array member functions instead
// of template arguments.

multi_array< int, 2 >::iterator it = matr.begin();
// use iterator it to fill matr with 0's
}
int _tmain(int argc, _TCHAR* argv[])
{
using namespace boost;
using namespace std;

boost::multi_array< int , 2 > matr(boost::extents[10][12]); //10
rows, 12 cols
fill_matrix(matr);
}

If this program runs okay for you, then we are no longer debating about
syntatic sugar. Please take a look at www.boost.org for more
information if you should wish. Thank you.


prefer boost::matrix

Aug 31 '05 #16

P: n/a
Aleksey, Yes MSVC7.1 _tmain() is not standard C++, but MSVC 7.1 is a
huge step toward conforming with standard C++. MSVC8.0 promises to be
even better in this respect.
fill<complex> vs f<> . First , it is easier to read. Second, it
absolutely guarantees that the user must pass a complex 2D array to
fill() or you will get a compiler error: ""'fill' : invalid template
argument for 'T', missing template argument list on class template"

Finally. I think the issue about boost::multiarray versus
boost::matrix has very little to do with the size of the program: R.
Garcia, possibly from www.boost.org, writes:

"First, bear in mind that there is a difference between a general
n-dimensional array library and a linear algebra library. While a
linear algebra library will tend to use two dimensional matrices to
represent linear transformations, some algorithms can make use of
matrix-free representations, where the matrix form of the
transformation never exists. In addition, operation semantics
(specifically operator*()) can differ depending on use."

My belief is that for this problem, boost_multi_array is more
appropriate.
Aleksey, what is view on this issue? Thank you.

Aug 31 '05 #17

P: n/a

Frank Chang wrote:

Finally. I think the issue about boost::multiarray versus
boost::matrix has very little to do with the size of the program: R.
Garcia, possibly from www.boost.org, writes:

"First, bear in mind that there is a difference between a general
n-dimensional array library and a linear algebra library. While a
linear algebra library will tend to use two dimensional matrices to
represent linear transformations, some algorithms can make use of
matrix-free representations, where the matrix form of the
transformation never exists. In addition, operation semantics
(specifically operator*()) can differ depending on use."

My belief is that for this problem, boost_multi_array is more
appropriate.
actually, i dont remember source problem :)
Aleksey, what is view on this issue?
i use c++ for pleasure and dont have big practical experience.
arrays and std::vector enough for me :)
Thank you.


at any time.

Sep 1 '05 #18

P: n/a
Aleksey, Please keep contributing your ideas in this newsgroup. Your
ideas are quite good. I have to admit this 2d array/matrix subject is
getting a bit repititive. Без перевода.
Sep 1 '05 #19

This discussion thread is closed

Replies have been disabled for this discussion.