How to use the same multidimensional array in many functions? - c++

I'm a beginner at C++ and to be honest, I've got no idea how to solve one task.
I have to create a matrix using a two dimensional array. It's size should be dependent on user's input (it should be like...int matrix[m][n], where m and n are the numbers entered by user). Then I'm supposed to fill it with random numbers from 0 to 100 and print it. Well, I can manage it.
The problem starts when I have to create a function finding the highest number from this array's row. The only parameter of this function can be the number of row entered by user (eg. int function(int i)).
The question is-how can I use the same array in multiple functions? Is there any way to do this, considering the fact that I'm a newbie?
Or maybe the task is formed incorrectly?
Sorry for the long post and thanks in advance
PS Someone asked for code, so here it is:
#include <iostream>
#include <cstdlib>
using namespace std;
int function1(int i)
{
//this is one of the functions I'm supposed to create-I described it earlier
}
int main()
{
int m,n;
cout<<"Matrix's size will be m rows and n columns. Please write m and n"<<endl;
cin>>m>>n;
int A[m][n];
int a,b;
for (a=0;a<m;a++)
{
for (b=0;b<n;b++)
{
A[a][b]=rand()%(100+1);
cout<<A[a][b]<<" ";
}
cout<<"\n";
}
}
EDIT: I'd like to thank you all for help guys. I asked my teacher about that and he finally responded. If you're curious, he told us (I hadn't heard it) to define an array like int[100][100] or higher and not allow user to input any higher numbers ;) That's not an optimal solution but surely a practical one. Thank you again!

The correct way to do this in C++ is to use a std::vector or std::array.
If you cannot do this because of artificial requirements, then there is simply no way you can declare a 2D array in C++ based on user input.
cin >> m >> n;
...
int array [m][n]; // not possible
int** wannabe; // not an array
int array [m * n]; // not possible
What you can do is a "mangled" 2D array:
int* mangled = new int[m * n];
Example of use:
class int_matrix
{
private:
int* mangled;
size_t rows;
size_t cols;
public:
int_matrix(size_t row, size_t col)
:rows(row),
cols(col)
{
mangled = new int[row * col];
}
int highest_in_row (size_t row)
{
...
}
};
Please note that this code requires that you follow the rule of three.
In C you would just have elegantly solved this by writing int array[m][n], but you are using C++ so you can't do that.

You can wrap your function into a class. In that class, you can have your array as member variable.
class A {
int **matrix;
public:
A(int rows, int columns) {
matrix = new int*[rows];
for(int i = 0; i < rows; ++i)
matrix[i] = new int[columns];
}
int function(int i); //you can use your matrix in this function
}
If you can't use classes, you can use global variables.
In a file.cpp
int **matrix;
int function(int i) {
//Do Something
}
//With rows the number of rows and columns the number of columns
//You can take these as parameters
int main() {
matrix = new int*[rows];
for(int i = 0; i < rows; ++i)
matrix[i] = new int[columns];
function(42);
}

If you declare a matrix like int int A[m][n]; where m and n aren't const, you can't pass it to a function. There are two ways to fix it:
1) Declare matrix with const size like int A[10][10];. In this case function which finds max will look like this:
int max_in_row(int matr[10][10], int row) {
int max = 0;
for (int col = 0; col < 10; ++col)
if (matr[row][col] > max)
max = matr[row][col];
return max;
}
and you can find max simple as int max = max_in_row(A, <row you want>);
2) (If you don't know size) Declare matrix as array of arrays:
int **A = new int*[n];
for (int i = 0; i < n; ++i)
A[i] = new int[m];
// fill A like you did
Then the function will look like
int max_in_row(int **matr, int row, int m) {
int max = 0;
for (int col = 0; col < m; ++col)
if (matr[row][col] > max)
max = matr[row][col];
return max;
}
and you can find max by int max = max_in_row(A, <row you want>, m);

The following is not standard C++ because it will only work if the compiler supports Variable Length Arrays. VLA were introduced in C99 and made optional in C11 but were never introduced in C++ standard - but some compilers support it even in C++ mode.
The hack will be to store the matrix address as a global void * and cast it to the proper pointer to VLA inside the function. This hack is required because at the moment of the global declaration you cannot know the number of columns of the matrix.
#include <iostream>
#include <cstdlib>
void *Matrix;
int Columns;
using namespace std;
int function1(int i)
{
typedef int MAT[Columns]; // BEWARE!!! VLA is not standard C++
MAT *mat = static_cast<MAT *>(Matrix);
int mx = mat[i][0];
for(int j=0; j<Columns; j++) {
cout << " " << mat[i][j];
if (mat[i][j] > mx) mx = mat[i][j];
}
std::cout << endl;
return mx;
}
int main()
{
int m,n;
cout<<"Matrix's size will be m rows and n columns. Please write m and n"<<endl;
cin>>m>>n;
int A[m][n]; // BEWARE!!! VLA is not standard C++
int a,b;
for (a=0;a<m;a++)
{
for (b=0;b<n;b++)
{
A[a][b]=rand()%(100+1); // Note that I now use a and b here !
cout<<A[a][b]<<" ";
}
cout<<"\n";
}
Matrix = static_cast<void *>(A);
Columns = n;
cout << "Enter row number to process: ";
cin >> a;
b = function1(a);
cout << "Max of row " << a << " is " << b << endl;
return 0;
}
Not really C++-ish, but at least it compiles and give expected results with clang version 3.4.1

Related

Stack Overflow-Matrix Multiplication [duplicate]

This question already has answers here:
Declare large array on Stack
(4 answers)
Closed 9 months ago.
I am programming for simple matrices multiplication. However, for large values of matrix size, I faced with matrix overflow error. Could someone help me with this.
here the code!
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int r,c;
cout<<"Rows: ";
cin>>r; // 5000
cout<<"Clumns: ";
cin>>c; // 5000
int m[r][c];
for (int i=0;i<r;i++)
{
for (int j=0;j<c;j++)
{
m[i][j]=i+j;
cout<<setw(4)<<m[i][j];
}
cout<<endl;
}
}
I ran your program with different sizes. And the problem is simply that the array is too big. It works with smaller array sizes, but you can only put so much onto the stack.
So I did this:
#include <iostream>
#include <iomanip>
using namespace std;
class Matrix {
public:
Matrix(int r, int c)
: rows(r), cols(c)
{
m = new int *[rows];
for (int index = 0; index < rows; ++index) {
m[index] = new int[cols];
}
}
int & at(int r, int c) {
return m[r][c];
};
int rows = 0;
int cols = 0;
int ** m = nullptr;
};
int main(int argc, char **argv)
{
int r = atoi(argv[1]);
int c = atoi(argv[2]);
Matrix m(r, c);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
m.at(i, j) = i+j;
cout << setw(4) << m.at(i, j);
}
cout<<endl;
}
}
And that appears to work. Now, there are some things in here that are bad. I didn't write a destructor, so there's a memory leak. And I didn't do any range checking in the at() method. I was only showing what you could do for very large arrays.
Now, I'm going to beg you... PLEASE put white space in your code. You're going to have no end of errors when you shove everything together the way you do. Notice my for-loops have a lot more space than you do. I didn't fix everywhere, but the coding policy where I work is to include white space for readability. Walls of numbers and operators can be very, very hard to read.
Also, name your variables something longer than a single character.
Both these changes will dramatically reduce future bugs.

Inputing the Size of a 2-dimentional Array

In my code I input the sizes of both dimensions and then declare a two-dimensional array. My question is, how do I use that array as a function parameter? I know that I need to write the number of columns in the function specification but how do I pass the number of columns?
void gameDisplay(gameCell p[][int &col],int a,int b) {
for(int i=0;i<a;i++) {
for(int j=0;j<b;j++) {
if(p[i][j].getStat()==closed)cout<<"C ";
if(p[i][j].getStat()==secure)cout<<"S ";
if(p[i][j].getBomb()==true&&p[i][j].getStat()==open)cout<<"% ";
if(p[i][j].getBomb()==false&&p[i][j].getStat()==open) {
if(p[i][j].getNum()==0)cout<<"0 ";
else cout<<p[i][j].getNum()<<" ";
}
cout<<endl;
}
}
}
int main() {
int row,col,m;
cout<<"Rows: ";cin>>row;cout<<"Columns: ";cin>>col;
m=row*col;
gameCell p[row][col];
gameConstruct(p[][col],m);
gameDisplay(p[][col],row,col);
}
I tried this way but it doesn't work.
Thank you.
In C++, you cannot have variable length arrays. That is, you can't take an input integer and use it as the size of an array, like so:
std::cin >> x;
int array[x];
(This will work in gcc but it is a non-portable extension)
But of course, it is possible to do something similar. The language feature that allows you to have dynamically sized arrays is dynamic allocation with new[]. You can do this:
std::cin >> x;
int* array = new int[x];
But note, array here is not an array type. It is a pointer type. If you want to dynamically allocate a two dimensional array, you have to do something like so:
std::cin >> x >> y;
int** array = new int*[x]; // First allocate an array of pointers
for (int i = 0; i < x; i++) {
array[i] = new int[y]; // Allocate each row of the 2D array
}
But again, this is still not an array type. It is now an int**, or a "pointer to pointer to int". If you want to pass this to a function, you will need the argument of the function to be int**. For example:
void func(int**);
func(array);
That will be fine. However, you almost always need to know the dimensions of the array inside the function. How can you do that? Just pass them as extra arguments!
void func(int**, int, int);
func(array, x, y);
This is of course one way to do it, but it's certainly not the idiomatic C++ way to do it. It has problems with safety, because its very easy to forget to delete everything. You have to manually manage the memory allocation. You will have to do this to avoid a memory leak:
for (int i = 0; i < x; i++) {
delete[] array[i];
}
delete[] array;
So forget everything I just told you. Make use of the standard library containers. You can easily use std::vector and have no concern for passing the dimensions:
void func(std::vector<std::vector<int>>);
std::cin >> x >> y;
std::vector<std::vector<int>> vec(x, std::vector<int>(y));
func(vec);
If you do end up dealing with array types instead of dynamically allocating your arrays, then you can get the dimensions of your array by defining a template function that takes a reference to an array:
template <int N, int M>
void func(int (&array)[N][M]);
The function will be instantiated for all different sizes of array that are passed to it. The template parameters (dimensions of the array) must be known at compile time.
I made a little program:
#include <iostream>
using namespace std;
void fun(int tab[][6], int first)
{}
int main(int argc, char *argv[])
{
int tab[5][6];
fun(tab, 5);
return 0;
}
In function definition you must put size of second index. Number of column is passed as argument.
I'm guessing from Problems with 'int' that you have followed the advices of the validated question and that you are using std::vector
Here is a function that returns the number of columns of an "array" (and 0 if there is a problem).
int num_column(const std::vector<std::vector<int> > & data){
if(data.size() == 0){
std::cout << "There is no row" << std::endl;
return 0;
}
int first_col_size = data[0].size();
for(auto row : data) {
if(row.size() != first_col_size){
std::cout << "All the columns don't have the same size" << std::endl;
return 0;
}
}
return first_col_size;
}
If you're using C-style arrays, you might want to make a reference in the parameter:
int (&array)[2][2]; // reference to 2-dimensional array
is this what you're looking for?
int* generate2DArray(int rowSize, int colSize)
{
int* array2D = new int[rowSize, colSize];
return array2D;
}
example . . .
#include <iostream>
#include <stdio.h>
int* generate2DArray(int rowSize, int colSize);
int random(int min, int max);
int main()
{
using namespace std;
int row, col;
cout << "Enter row, then colums:";
cin >> row >> col;
//fill array and display
int *ptr = generate2DArray(row, col);
for(int i=0; i<row; ++i)
for(int j=0; j<col; ++j)
{
ptr[i,j] = random(-50,50);
printf("[%i][%i]: %i\n", i, j, ptr[i,j]);
}
return 0;
}
int* generate2DArray(int rowSize, int colSize)
{
int* array2D = new int[rowSize, colSize];
return array2D;
}
int random(int min, int max)
{
return (rand() % (max+1)) + min;
}
instead of accessing p[i][j] you should access p[i*b + j] - this is actually what the compiler do for you since int[a][b] is flattened in the memory to an array in size of a*b
Also, you can change the prototype of the function to "void gameDisplay(gameCell p[],int a,int b)"
The fixed code:
void gameDisplay(gameCell p[],int a, int b) {
for(int i=0;i<a;i++) {
for(int j=0;j<b;j++) {
if(p[i*a +j].getStat()==closed)cout<<"C ";
if(p[i*a +j].getStat()==secure)cout<<"S ";
if(p[i*a +j].getBomb()==true&&p[i][j].getStat()==open)cout<<"% ";
if(p[i*a +j].getBomb()==false&&p[i][j].getStat()==open) {
if(p[i*a +j].getNum()==0)cout<<"0 ";
else cout<<p[i*a +j].getNum()<<" ";
}
cout<<endl;
}
}
}
int main() {
int row,col,m;
cout<<"Rows: ";cin>>row;cout<<"Columns: ";cin>>col;
m=row*col;
gameCell p[row][col];
gameConstruct(p[][col],m);
gameDisplay(p[],row,col);
}

How to pass two dimensions array to a function and how to call it

I've tried many time to pass the array to a function then do some calculation such as getting the total of the columns, the problem is I don't know how to call the result form the function, usually I get errors.
this is just one code I'm trying to solve it from yesterday :
#include <iostream>
using namespace std;
//prototype
int get_total(int whatever[][2], int row);
int main ()
{
const int row=2;
const int col=3;
int marks[row][col];
// this is prompt the user to input the values
for (int i=0; i<row;i++)
{
for (int p=0; p<col; p++)
{
cin >> marks[i][p];
}
cout << endl;
}
// this is just display what the user input as a table
for (int x=0; x< row ; x++)
{
for (int y=0; y<col ; y++)
{
cout << marks[x][y] << " ";
}
cout << endl;
}
int sum;
// this is the most important thing I want to know,
// how to call the function :(
sum=get_total(marks,row);
return 0;
}
// to get the total of each columns
const int row=3;
// not sure if the declaration is correct or not :(
int get_total(int whatever[][2], int row)
{
for (int i=0; i < 2; i++)
{
for (int p=0; p < 3; p++)
int total=0;
//this line is completly wrong, How can I calculate the total of columns?
total+=get_total[2][p];
}
// do we write return total ?
// I'm not sure because we need the total for each column
return total;
}
sorry for the mess, and I appreciate any help to explain passing the multidimensions arry to a function as parameter and how to call the function>
Arrays decay to pointers when calling functions.
You can do 2 things:
Pass the number of lines and columns as arguments to the function.
Use std::vector instead. I suggest you take a look at it, it'll do the trick and you'll learn something new and very useful.
Also, your function should do this:
int get_total(int** whatever)
{
//total is 0 at the beginning
int total=0;
for (int i=0; i < 2; i++)
{
for (int p=0; p < 3; p++)
//go through each element and add it to the total
total+=whatever[i][p];
}
return total;
}
This will return the total for the whole matrix, I'm assuming that's what you mean by getting the total of the columns
int marks[row][col]
This means that marks has type int[2][3].
int get_total(int whatever[][2], int row);
You've however declared get_total to accept an int(*)[2]. int[2][3] can decay to int(*)[3] but that is not compatible with int(*)[2], hence why you can't pass marks to get_total. You can instead declare get_total to accept an int(*)[3]:
int get_total(int whatever[][3], int row);
// equivalent to:
int get_total(int (*whatever)[3], int row);
If you instead decide to declare get_total to accept an int** or an int*, then you can't legally pass marks to it in the former case, and you can't legally iterate over the whole multidimensional array in the latter. Consider not using arrays, it's simpler this way.

How do I pass multi-dimensional arrays of unknown size into a function using pointers in c++?

Like the question says, I am trying to pass multi-dimensional arrays into a function to print it to a file for an engineering project. The format for which the data is inputted CANNOT be changed, so please don't suggest I just input it as a different datatype.
This particular function anticipates a two-dimensional array (although I have others with three dimensions after this one), where nothing is known about the size of the array until run-time. I know I must use pointers to point to each row of the array separately, but I have NO idea what the syntax is for passing it to the function. In the following code, the array in question is 'block'. The main function is just a little testing example I made to try to make it work:
#include<fstream>
using namespace std;
void of_write_blocks(string filename, string block_type[], int **block,
int grid[][3], string grade_type[], int grade[][3], int n_blocks, int m[])
{
ofstream file_out(filename.c_str(),ios::app);
file_out<<"\nblocks\n(\n";
for(int i=0;i<n_blocks;++i) {
file_out<<" "<<block_type[i]<<" ( ";
for(int j=0;j<m[i];++j)
file_out<<block[i][j]<<" ";
file_out<<") ( ";
file_out<<grid[i][0]<<' '<<grid[i][1]<<' '<<grid[i][2]<<" ) ";
file_out<<grade_type[i]<<" ( ";
file_out<<grade[i][0]<<' '<<grade[i][1]<<' '<<grade[i][2]<<" )\n";
}
file_out<<");\n";
}
//testing example:
int main()
{
int block[6][9];
for(int i=0; i<6;++i)
for(int j=0; i<9;++j)
block[i][j] = i*j;
int grid[6][3];
for(int i=0; i<6;++i)
for(int j=0; i<3;++j)
block[i][j] = i*j;
int grade[6][3];
for(int i=0; i<6;++i)
for(int j=0; i<3;++j)
block[i][j] = i*j;
string grade_type[6] = {"simpleGrading"};
string block_type[6] = {"hex"};
int m[6] = {8};
int n_blocks = 6;
of_write_blocks("name",block_type,block,grid,grade_type,grade,n_blocks,m);
}
any help is appreciated!
You can't. Multidimensional arrays are syntactic sugar, and are compiled directly into the code that does manipulations on the array, which is a single memory block. The dimensions are not passed into the function as parameters or anything like that as part of the array, as things are done in e.g. Java or C#.
If you need the dimensions of the array in your function, you'll need to just accept a pointer to the first element of the array, and the dimensions, and do the multiplies and adds to get the right index yourself.
Alternately, use something like a std::vector<std::vector<block>>, which pass the dimensions as part of the object, rather than a built in array.
If you have Boost installed, check out Boost Multi-Array.
For clarity I removed all the irrelevant code from your example.
#include <iostream>
#include <fstream>
using namespace std;
void of_write_blocks(int **block, int bh, int bw){
for(int i = 0; i < bh; ++i)
for(int j = 0; j < bw; ++j)
cout << block[i][j] << " ";
cout << endl;
}
int main(){
int bh, bw;
cin >> bh >> bw;
int** block;
block = new int*[bh];
for(int k = 0; k < bh; k++)
block[k] = new int[bw];
// initialize the array
for(int i = 0; i < bh; i++)
for(int j = 0; j < bw; j++)
block[i][j] = (i*bw) + j;
of_write_blocks( block, bh, bw);
}
In the main we are creating a 2D array and initializing it. Then we pass it to of_write_block, which prints the array. Is that what you wanted to do?
Why can't use a reference of array. See below example:
char c[10];
int i[10][20];
double d[10][20][30];
Write a wrapper function like this:
template<typename T, int SIZE>
void Array (T (&a)[SIZE])
{}
template<typename T, int SIZE1, int SIZE2>
void Array (T (&a)[SIZE1][SIZE2])
{}
template<typename T, int SIZE1, int SIZE2, int SIZE3>
void Array (T (&a)[SIZE1][SIZE2][SIZE3])
{}
This is just an example to demonstrate the syntax which will elegantly receive the array without any copying and also avoids confusing pointers. Also, if you are aware that you are going to use only for int then simply remove the typename and explicitly mention int. i.e.
template<int SIZE>
void Array (int (&a)[SIZE]); // explicitly mention int

C++ passing Dynamically-sized 2D Array to function

I'm trying to figure out how to pass 2D array, which is constructed dynamically to a function.
I know that number of columns must be specified, but it my case it depends on user input.
Are there any workarounds?
Example:
// Some function
void function(matrix[i][j]) {
// do stuff
}
// Main function
int N;
cout << "Size: ";
cin >> N;
int matrix[N][N];
for (int i=0;i<N;i++) { //
for (int j=0;j<N;j++) {
cin >> matrix[N][N];
}
}
sort(matrix);
You get the idea :)
If you're on C++, the reasonable options are to:
use boost::multi_array (recommended), or
make your own 2D array class. Well, you don't have to, but encapsulating 2D array logic in a class is useful and makes the code clean.
Manual 2D array indexing would look like this:
void func(int* arrayData, int arrayWidth) {
// element (x,y) is under arrayData[x + y*arrayWidth]
}
But seriously, either wrap this with a class or enjoy that Boost already has that class ready for you. Indexing this manually is tiresome and makes the code more unclean and error-prone.
edit
http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html says that C99 has one more solution for you:
void func(int len, int array[len][len]) {
// notice how the first parameter is used in the definition of second parameter
}
Should also work in C++ compilers, but I haven't ever used this approach.
In C++, the compiler can figure out the size, since it's part of the type. Won't work with dynamically sized matrices though.
template<size_t N, size_t M>
void function(int (&matrix)[N][M])
{
// do stuff
}
EDIT: In GCC only, which is required for your code defining the array, you can pass variable-length arrays directly:
void func(int N, int matrix[N][N])
{
//do stuff
}
See the gcc documentation
/*******************************************************\
* *
* I am not claiming to be an expert, but I think I know *
* a solution to this one. Try using a Vector Container *
* instead of an array. Here is an example below: *
* *
* Load the target file with a Multiplication Table *
* *
* *
\*******************************************************/
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
std::string user_file;
int user_size = 2;
void array_maker(int user_size, std::string user_file);
int main () {
std::cout << "Enter the name of the file for your data: ";
std::cin >> user_file;
std::cout << std::endl;
std::cout << "Enter the size for your Multiplication Table: ";
std::cin >> user_size;
// Create the users Multiplication data
array_maker(user_size, user_file);
return (0);
}
void array_maker(int user_size, std::string user_file)
{
// Open file to write data & add it to end of file
std::ofstream target_file(user_file,std::ios::out | std::ios::app);
// Declare the vector to use as a runtime sized array
std::vector<std::vector<int>> main_array;
// Initialize the size of the vector array
main_array.resize(user_size+1); // Outer Dimension
for (int i=0; i <= user_size; ++i) // Inner Dimension
{
main_array[i].resize(user_size+1);
}
for (int i=0; i<=user_size; ++i)
{
for (int j=0; j<=user_size; ++j)
{
main_array[i][j] = i * j;
// output line to current record in file
target_file << i << "*"
<< j << "="
<< main_array[i][j] << " "
<< "EOR" // End of Record
<< std::endl;
} // Close Inner For
} // Close Outer For
// close file
target_file.close();
} // Close array_maker function
You can do
void function (int** __matrix, int32_t __row, int32_t __column)
__row - max rows
__column - max columns.
You will need those params to find out the limits of the array.
Just add another parametrs to your function - row_number and column_number. Arrays are not object in C++ so they don't store any additional information about themselfs.
If you pass in the array identifier (as a pointer to a pointer) you will need to use pointer arithmetic:
void function(int** matrix, int num_rows, int num_cols) {
Assert(matrix!=NULL && *matrix!=NULL && num_rows>0 && num_cols>0);
for(int i=0; i<num_rows; i++) {
for(int j=0; j<num_cols; j++) {
// cannot index using [] like matrix[i][j]
// use pointer arithmetic instead like:
// *(matrix + i*num_cols + j)
}
}
}
to pass multi dimensional arays into method the compiler needs to know the depth of each field, so one solution is to use templates and call method in a normal way and the compiler will guess the size of each field.
template <size_t m>
void method(int M[][m])
{
for(int i=0; i<m; ++i)
for(int j=0; j<m; ++j)
{
// do funny stuff with M[i][j]
}
}
int main()
{
int M[5][5] = { {1,0,1,1,0}, {0,1,1,1,0}, {1,1,1,1,1}, {1,0,1,1,1}, {1,1,1,1,1} };
method(M);
// also you can call with method<5>(M)
// if you have different sizes for each dimension try passing them in args
return 0;
}
int r, c
int *matrix = new int[r,c];
for (int i = 0; i < r; i++)
{
/*cout << "Enter data" << endl;*/
for (int j = 0; j < c; j++)
{
cin >> matrix[i,j];
}
}
void function(int &matrix[][] )