passing a 2d array as a paramater

L

laclac01

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

Code:
#include<iostream>
using namespace std;

int main()
{
   int array[10][10];
   fill(array,rows,cols);
   return 0;

}
void fill(int array[10][10], rows,cols)
{
   int i, j;

   for(i=0;i<10;i++)
   for(j=0;j<10;j++)
   array[i][j]=0;
}
array needs to have the [10][10] or at least
[][10]. is there a way i can make it so it
only needs [][]?
 
J

John Ratliff

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

Code:
#include<iostream>
using namespace std;

int main()
{
int array[10][10];
fill(array,rows,cols);
return 0;

}
void fill(int array[10][10], rows,cols)
{
int i, j;

for(i=0;i<10;i++)
for(j=0;j<10;j++)
array[i][j]=0;
}
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
 
K

Kai-Uwe Bux

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

Code:
#include<iostream>
using namespace std;

int main()
{
int array[10][10];
fill(array,rows,cols);
return 0;

}
void fill(int array[10][10], rows,cols)
{
int i, j;

for(i=0;i<10;i++)
for(j=0;j<10;j++)
array[i][j]=0;
}
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 COLSclass 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 COLSvoid 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
 
D

David Hilsee

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

Code:
#include<iostream>
using namespace std;

int main()
{
int array[10][10];
fill(array,rows,cols);
return 0;

}
void fill(int array[10][10], rows,cols)
{
int i, j;

for(i=0;i<10;i++)
for(j=0;j<10;j++)
array[i][j]=0;
}
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.
 
F

Frank Chang

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;
}
}
 
K

Kai-Uwe Bux

Frank said:
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
 
F

Frank Chang

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

Aleksey Loginov

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

Code:
#include<iostream>
using namespace std;

int main()
{
int array[10][10];
fill(array,rows,cols);
return 0;

}
void fill(int array[10][10], rows,cols)
{
int i, j;

for(i=0;i<10;i++)
for(j=0;j<10;j++)
array[i][j]=0;
}
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])

?
 
F

Frank Chang

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[j]=0;
}


int _tmain(int argc, _TCHAR* argv[])
{
Complex array[10][10];
fill<Complex>(array);
}
 
D

Dave Rahardja

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[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.reserve(10);
for (int j = 0; j < 10; ++i) {
array[j] = 0;
}
}
}

....
 
D

David Hilsee

Dave Rahardja said:
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[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.reserve(10);
for (int j = 0; j < 10; ++i) {
array[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.
 
A

Aleksey Loginov

Frank said:
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
 
D

Dave Rahardja

Dave Rahardja said:
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[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.reserve(10);
for (int j = 0; j < 10; ++i) {
array[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.
 
E

E. Robert Tisdale

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[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[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.
 
F

Frank Chang

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

Aleksey Loginov

Frank said:
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 said:
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
 
F

Frank Chang

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

Aleksey Loginov

Frank said:
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.
 
F

Frank Chang

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. Без перевода.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,150
Latest member
MakersCBDReviews
Top