Cannot pass 2d array into a helper function in c++ - c++

I was learning c++ and implementing the game of life when I created a helper function to print the current board which is a 2d array. I cannot seem to pass the array into the function as I get an error, "Candidate function not viable: no known conversion from 'char [rows][cols]' to 'char (*)[cols]' for 3rd argument." I am using Xcode as an ide if that helps.
void printArray(int rows, int cols, char board[rows][cols]){
for(int r = 0; r < rows; r++){
for(int c = 0; c < cols; c++){
cout << board[r][c];
cout << " ";
}
cout << "\n";
}
}
int main(){
char board[5][5];
for(int r = 0; r < 5; r++){
for(int c = 0; c < 5; c++){
board[r][c] = 0;
}
}
printArray(5, 5, board);
return 0;
}
I've tried switching up the parameter to different things such as char **board, char board[][cols], char (*board)[cols]. Even casting my input board which leads to other errors.

If you want to pass 2d arrays to a function there is a special syntax. Unfortunately, the other previous 2 answers do not answer fully correctly.
You can pass by reference or by pointer. The array dimensions must be compile time constants. That is a requirement from C++.
Please see:
constexpr size_t NumberOfRows = 3;
constexpr size_t NumberOfColumns = 4;
// Typedef for easier usage
using IntMatrix2d = int[NumberOfRows][NumberOfColumns];
//Solution 1 ------
// Pass by reference
void function1(int(&matrix)[NumberOfRows][NumberOfColumns]) {}
// Pass by pointer
void function2(int(*m)[NumberOfRows][NumberOfColumns]) {}
//Solution 2 ------
// Pass by reference
void function3(IntMatrix2d& matrix) {}
// Pass by pointer
void function4(IntMatrix2d* matrix) {}
int main()
{
// Solution 1
// Handwritten matrix. Dimension is compile time constant
int matrix1[NumberOfRows][NumberOfColumns];
// Pass by reference
function1(matrix1);
// Pass by pointer
function2(&matrix1);
// Solution 2 -----
IntMatrix2d matrix2;
// Pass by reference
function3(matrix2);
// Pass by pointer
function4(&matrix2);
return 0;
}
If you typedef or use using for your type definition, then it gets rather intuitive.

If you are not very comfortable with pointers then there are some easy ways to do the task
1. You have to define the 2d array size by default, before passing array to the function so that the size doesn't seem to be unknown to the function.
#include <iostream>
const std::size_t rows=5;
const std::size_t cols=5;
void printArray(char board[rows][cols]) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
std::cout << board[r][c];
std::cout << " ";
}
std::cout << "\n";
}
}
int main() {
char board[rows][cols];
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
board[r][c] = '0';
}
}
printArray(board);
return 0;
}
2. Use vector. Make your board a vector.
#include <iostream>
#include <vector>
void printArray(std::vector<std::vector<char>> &board) {
for (int r = 0; r < board.size(); r++) {
for (int c = 0; c < board[0].size(); c++) {
std::cout << board[r][c];
std::cout << " ";
}
std::cout << "\n";
}
}
int main() {
std::vector<std::vector<char>> board(rows, std::vector<char>(cols, '0'));
printArray(board);
}

I encountered this problem while doing a project for a class. To work around it, I made a double pointer array, and then used passed it to the function to manipulate it.
int** createArr(){
int** pixels = 0;
pixels = new int*[numrows];
for (int row = 0; row < numrows; row++){
pixels[row] = new int[numcols];
for (int col = 0; col < numcols; col++){
ss >> pixels[row][col];
}
}
return pixels;
}
int** newArr = createArr(); //calls function to create array
func(newArr); //where func is a function that modifies the array.
Don't forget to delete your arrays at the end to avoid memory leaks. Hope this helps.

Related

Calling a boolean function but getting error "no matching function to call"?

I am trying to declare 2d arrays dynamically and fill them with random numbers and then create a function that will compare the elements in two 2d arrays and if they were equal it will return true
However, i keep getting error when trying to call the boolean function.
#include <iostream>
#include <cstdlib>
using namespace std;
bool isEqual(int *arr1[], int *arr2[], bool &eq, int row, int col){
for(int r = 0; r<row;r++)
{
for(int c= 0; c<col;r++)
{
if(arr1[r][c]==arr2[r][c])
eq = true;
}
}
return eq;
}
int main()
{
const int R = 3;
int * arr2D_a[R];
int * arr2D_b[R];
int C;
cout << "Enter number of columns: ";
cin >> C;
for (int r = 0; r < R; r++) {
arr2D_a[r] = new int [C];
arr2D_b[r] = new int [C];
}
for (int r = 0; r < R; r++) {
for (int c = 0; c < C; c++) {
arr2D_a[r][c] = rand() % 2;
arr2D_b[r][c] = rand() % 2;
}
}
bool result = false;
isEqual(arr2D_a,arr2D_b,result,R,C);
if (result==true)
cout << "\nThe 2 array are the same!\n";
else
cout << "\nThe 2 array are the differernt!\n";
for (int c = 0; c < C; c++) {
delete[] arr2D_a[C];
delete[] arr2D_b[C];
}
for (int r = 0; r < R; r++) {
delete[] arr2D_a[r];
delete[] arr2D_b[r];
}
system("pause");
}
EDIT i took the liberty of rewriting your code. the code i posted, compiled in VS2017.
your compare seems kind off
#include <iostream>
#include <cstdlib>
using namespace std;
bool isEqual(int* arr1[], int* arr2[], const int row, const int col) {
for (int r = 0; r < row; r++)
{
for (int c = 0; c < col; c++)
{
if (arr1[r][c] != arr2[r][c])
return false;
}
}
return true;
}
int main()
{
const int R = 3;
int * arr2D_a[R];
int * arr2D_b[R];
int C;
cout << "Enter number of columns: ";
cin >> C;
for (int r = 0; r < R; r++) {
arr2D_a[r] = new int[C];
arr2D_b[r] = new int[C];
}
for (int r = 0; r < R; r++) {
for (int c = 0; c < C; c++) {
int value = rand();
arr2D_a[r][c] = value % 2;
arr2D_b[r][c] = value % 2;
}
}
bool result = isEqual(arr2D_a, arr2D_b, R, C);
if (result)
cout << "\nThe 2 array are the same!\n";
else
cout << "\nThe 2 array are the differernt!\n";
for (int r = 0; r < R; r++) {
delete[] arr2D_a[r];
arr2D_a[r] = 0;
delete[] arr2D_b[r];
arr2D_b[r] = 0;
}
return 0;
}
you have to declare your parameters for your function right. bool isEqual(int arr1, int** arr2, bool &eq, int row, int col)** because you have a 2D array
check if the values diff, escape the function as soon as they do. there is no need for a bool variable
i dont know if it was intentional, but your init of the arrays. there was no way that they could have matched. you called rand() everytime, so the values can't match
was a little thing with the delete of the columns. you have to use your index c not the variable C
this i did not change... pls don't use using namespace std;. this namespace is so enormously huge. when you define your own functions, you can run into undebugable errors, when you declare a function with a name that exists.
EDIT 2
I totally removed the bool in the function call...
EDIT 3
to leave this program for good you have to provide a return value
another mistake was, you must not make the second delete loop. since you have not dynamically allocated this memory.
EDIT 4
reworked the function to please all the compilers =)
EDIT 5
i hope its the last edit for this answer^^ i fixed the memory issue. i checked it with dr. memory and he says, everything is ok :D
The answer above fixes most of the issues, but you will get segfault her.
for (int c = 0; c < C; c++) {
delete[] arr2D_a[c];
delete[] arr2D_b[c];
}
if you put something greater than 3 up here
std::cin >> C;
What you need to do is leave the second loop:
for (int r = 0; r < R; R++) {
delete[] arr2D_a[r];
delete[] arr2D_b[r];
}
because you allocated C amount of space in every arr2D_a[r] and arr2D_b[r].

Why I can manipulate dynamic matrix without reference

Let it be a create function for a dynamical allocated array:
void create(int *&a, int dim){
a=new int[dim];
for(int i=0;i<dim;i++){
a[i]=i+1;
}
Here, I need reference (&).
Now, I have a create function for a dynamical allocated matrix:
void create(int **&a,/* int**a, */ int lines,int rows){
...
}
I saw that reference is optional for dynamical allocated matrix create function. Why?
You need reference if you want to allocate the "outer" array - lines. Without it, you can allocate only "inner" arrays - rows (if "outer" array has been already allocated). So in your case, reference is mandatory.
void create(int **a, int lines, int rows)
{
a = new int*[lines]; // passed pointer to 'a' will point to an old address
for(int i = 0; i < lines; i++)
a[i] = new int[rows];
}
If you want to modify the pointer passed to a function inside the function, it needs to be passed by reference.
So no, the reference is not optional in your case. Wherever you saw that it's optional, was wrong.
My bad. I'm sorry.
I saw that refference in assignValues function isn't necessary so I thought that it is unnecessary for the create function, too.
Thank you all for replies.
Again, I'm sorry.
Here is my code:
#include <iostream>
#include <conio.h>
using namespace std;
void create(int **&a, int lines, int rows){
int i;
a = new int*[lines];
for (i = 0; i < lines; i++){
a[i] = new int[rows];
}
}
void assignValues(int **a, int lines, int rows){
int i,j,k = 1;
for (i = 0; i < lines; i++){
for (j = 0; j < rows; j++){
a[i][j] = k;
k++;
}
}
}
void print(int **a, int lines, int rows){
int i, j;
cout << "Matrix is: "<<endl;
for (i = 0; i < lines; i++){
for (j = 0; j < rows; j++){
printf("%3d",a[i][j]);
}
cout << endl;
}
}
int main()
{
int lines = 5;
int rows = 4;
int **a = 0;
create(a, lines, rows);
assignValues(a, lines, rows);
print(a, lines,rows);
_getch();
return 0;
}

How to pass and return 3d array to a function in c++?

I have created a 3d array into main function because one of its size came from used input. I am using C++
std::cin >> size;
typedef int T[8][3];
T* tables = new T[size];
It is basically tables[size][8][3]
Now I have to use this 3d table in different functions and have to store values into it. The best way to do it by make this table as a global variable. But I am not sure that I can do it after main function. The other option I have, that I have to pass this table as a parameter and have to return that at the end of the function.
I have tried both the approach but I am having error. Please help me about this issue. I don't know which approach to choose and how to do it.
Thank you in advance.
**Example:**This an example what I really want to do. Here I create a 3d array in main function and through another function I gave some input into that array and again print that in main function.
#include <iostream>
#include <conio.h>
using namespace std;
class M
{
public:
int i,j,k;
public:
int pass(int (*table)[8][3],int size);
}
int M:: pass(int (*table)[8][3],int s)
{
for (i=0;i<s;i++)
{
//int a = tables[i][2][1];
for(j=0;j<8;j++)
{
for(k=0;k<3;k++)
{
table[i][j][k]=i;
}
}
}
return (*table)[8][3]; // not sure about this
}
int main()
{
int size,i,j,k;
std::cin >> size;
typedef int T[8][3]; // T is your 2d array type
T* tables = new T[size];
cout << "test";
M mx;
mx.pass(tables,size); // not sure
for (i=0;i<size;i++)
{
for(j=0;j<8;j++)
{
for(k=0;k<3;k++)
{
cout<<tables[i][j][k];
cout<<" ";
}
cout<<endl;
}
cout<<endl;
cout<<"..........." << i <<endl;
}
getch();
}
I don't know if I completely understand your problem. But you can definitely store the pointer locally in your object and reference it elsewhere. Something like this:
class M
{
public:
M(int(*tbl)[8][3]) : table(tbl) { }
int(*table)[8][3];
int i, j, k;
public:
void pass(int size);
};
void M::pass(int s)
{
for (i = 0; i<s; i++)
{
for (j = 0; j<8; j++)
{
for (k = 0; k<3; k++)
{
table[i][j][k] = i;
}
}
}
}
int main()
{
int size, i, j, k;
std::cin >> size;
typedef int T[8][3]; // T is your 2d array type
T* tables = new T[size];
cout << "test";
M mx(tables);
mx.pass(size); // not sure
for (i = 0; i<size; i++)
{
for (j = 0; j<8; j++)
{
for (k = 0; k<3; k++)
{
cout << tables[i][j][k];
// or you can also:
// cout << mx.table[i][j][k];
cout << " ";
}
cout << endl;
}
cout << endl;
cout << "..........." << i << endl;
}
_getch();
}
Since you are creating a dynamic 3D array whose two dimensions are fixed, Use a std::array<std::array<int, 3>, 8> as your 2D array. Use a std::vector<__2D_ARRAY_TYPE> to create the 3D array.
#include <iostream>
#include <array>
#include <vector>
int main() {
std::array<std::array<int, 3>, 8> array_2d ;
std::vector<decltype(array_2d)> array_3d ;
int size = 4 ;
for(int i = 0; i < size; ++i)
{
for(int j = 0; j < 8; ++j)
for(int k = 0; k < 3; ++k)
array_2d[j][k] = j + k ;
array_3d.push_back(array_2d);
}
return 0;
}
Something like this you can use easily which does the job more easily without any manual memory management.
You can pass it to a function. The signature would be :
return_type function_name(const std::vector<std::array<std::array<int, 3>, 8>>& array_3d)
{ .... }
In
class M
{
public:
int i,j,k;
public:
int pass(int (*table)[8][3],int size);
}
you don't have to write public twice. You can simply put all of the public member data under the keyword public.
Also, you seem to be re-writing your function over again at the very end. Instead of
cout<<tables[i][j][k];
You can write
cout<<*tables

Passing custom size multidimensional array to function

I have array with known x size (5) and the y is taken from variable, so the array is something like this - array[5][y];
And now I'm quite troubled how to pass it to function, I won't edit it, just read the data from it.
I thought to do something like this:
void someFunction(double **array)
but I get
convert error: cannot convert `double (*)[((unsigned int)((int)n))]' to `double**' for argument `2' to `void findMax(int, double**, int)'|
For Array [5][x]
Unfortunately you cannot define a type for an array like double[5][]. You can only omit the first dimension of a multidimensional array, not the last.
For Array [x][5]
You should go with void someFunction(double array[][5], int size).
And then you loop trough the elements with for (int i = 0; i < size; i++).
Example:
void someFunction(double array[][5], int size) {
for (int k = 0; i < size; i++)
for (int i = 0; i < 5; i++)
std::cout << array[k][i] << std::endl;
}
double a[10][5];
// populate data
someFunction(a, 10);
Usually it's preferred to use std:: containers instead of raw C arrays.
Take a look at std::vector for example.
If you are not using the STL, you can also do this:
void someFunction(double **mat, const int Xsize, const int Ysize )
{
for(unsigned int i = 0 ; i < Xsize ; ++i)
{
for(unsigned int j = 0 ; j < Ysize ; ++j)
{
std::cout << ((double *)mat + Ysize * i)[j] << " " ;
}
std::cout << std::endl;
}
return ;
}
And call the function like this:
int main(int argc, char** argv)
{
double matrice[2][3] = {{1,2,3},{4,5,6}};
someFunction( (double**)matrice, 2, 3 );
return 1;
}

Copying an Array? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I use arrays in C++?
I was having trouble copying an array to an array. I have a feeling it may be because of the use of pointers but correct me if I'm wrong.
My function is the following:
bool sodoku::rowTest(sodoku *arr[9][9])
{
int row = 0;
while(row < 9)
{
for(int j = 0; j < 9; j++)
{
for(int k = 0; k < 9; k++)
{
if(arr[row][j]->number == arr[row][j]->possibleNumbers[k])
{
for(int i = 0; i < 9; i++)
{
arr[row][i]->possibleNumbers[k] = 0;
}
}
for(int g = 0; g < 7; g++)
{
int t = 8;
arr[row][g]->possibleNumbers[k] = arr[row][t]->possibleNumbers[k];
}
cout << "arr row j num : " << arr[row][j]->possibleNumbers[k] << "row: " << row << " column: " << j << endl;
}
}
row++;
}
if(row == 9)
return true;
}
return true;
}
My little section of trouble is here:
for(int g = 0; g < 7; g++)
{
arr[row][g]->possibleNumbers[k] = arr[row][8]->possibleNumbers[k];
}
For some reason when I cout each element, the copying doesn't occur. Could anyone help me as to know why this would hhappen? I just want every array from arr[row][1]->possibleNumbers[k] to arr[row][7]->possibleNumbers[k] have the same values as arr[row][8]->possibleNumbers[k]. PossibleNumbers ranges from 0 to 9, if that helps.
If anyone could help that'd be great.
Thanks.
Array variables are not copied, but you can use std::copy.
Also, passing arrays by value leads to array decay, which means that a lvalue of T(&)[N] actually gets passed as T*. To prevent this, pass by reference instead.
Here is a generic helper function that does this for you:
#include <algorithm>
template <typename T, int N>
void copy(T(&dest)[N], T(&src)[N])
{
std::copy(dest, dest+N, src);
}
Now you can just say
char dest[5];
char src [5];
copy(dest, src); // provided same element type and size
Note also, that member arrays are copied
struct SudokuRow
{
unsigned char cells[9];
};
SudokuRow a, b;
a = b; // copies just fine