I am a newbie to C and I wanted to know what should I do. I need to write a program where the user will be filling the 2d array. I need to program to show the 2d array in the form of matrix and do some other things, like counting elements that are not 0. But I am stuck. I can't call functions in main(), because there is no matching call error. I suppose this is because of the array initializing, but I saw people on the internet who does
int arr[row][col];
Code:
#include <iostream>
#include <conio.h>
#include <iomanip>
using namespace std;
// for filling the 2d array
void fillTheMatrix(int **arr, int row, int col) {
cout << "Please, enter here the elements you want to use for the matrix A:\n";
for (int i = 0; i < row; i ) {
for (int j = 0; j < col; j ) {
cout << "a[" << i << "][" << j << "] = ";
cin >> arr[i][j];
}
}
}
// for viewing this s2d array as matrix
void theMatrixView(int **arr, int row, int col) {
cout << "The matrix A\n";
for (int i = 0; i < row; i ) {
for (int j = 0; j < col; j ) {
cout << setw(3) << arr[i][j] << "\t";
}
cout << endl;
}
}
int main() {
int row;
int col;
cout << "Please, enter the number of rows of the matrix A: " << endl;
cin >> row;
cout << "Please, enter the number of columns of the matrix A: " << endl;
cin >> col;
int arr[row][col];
// TASK 1
fillTheMatrix(arr, row, col); // No matching function for call to 'fillTheMatrix'
theMatrixView(arr, row, col); // // No matching function for call to 'theMatrixView'
return 0;
}
Can you help me fixing this problem? I would be glad to have any recommendations to refactor code.
CodePudding user response:
As suggested in the comments better way is to use std::vector, however if you really want to use raw C arrays, to have a correctly type passed in, you need to declare a pointer to pointers to dynamically allocated memory:
int** arr = new int*[row];
for (int i = 0; i < row; i)
{
for (int j = 0; j < col; j)
arr[i] = new int[col];
}
fillTheMatrix(arr, row, col);
theMatrixView(arr, row, col);
for (int i = 0; i < row; i)
{
delete[] arr[i];
}
CodePudding user response:
You used a so called VLA. A variable length array. In C this is perfectly fine. See here.
In C this is not allowed. Arrays in C must have a size which is known at compile time. So, a literal number, like 3. Or a const or, in C now a constexpr
.
Some compilers allow VLA also while compiling C program. We call this a "compiler extension". But if you follow strict C rules, it will result in an error.
To give you an alternative you can use the std::vector
in C . It hast the additional advantage that it knows its size. So, no need to pass “row” and “col” to all sub routines.
And, in C you should not use C-Style arrays at all. And even the use of new
and raw pointers for owned memory is discourages. Simply std::vector
. It is easy.
We will pass the 2d vector via reference to the sub-functions to avoid copying.
Please see:
#include <iostream>
#include <vector>
#include <conio.h>
#include <iomanip>
using namespace std;
// To save typing work
using IntVec2d = std::vector<std::vector<int>>;
// for filling the 2d array
void fillTheMatrix(IntVec2d& arr) {
cout << "Please, enter here the elements you want to use for the matrix A:\n";
for (int i = 0; i < arr.size(); i ) {
for (int j = 0; j < arr[i].size(); j ) {
cout << "a[" << i << "][" << j << "] = ";
cin >> arr[i][j];
}
}
}
// for viewing this s2d array as matrix
void theMatrixView(IntVec2d& arr) {
cout << "The matrix A\n";
for (int i = 0; i < arr.size(); i ) {
for (int j = 0; j < arr[i].size(); j ) {
cout << setw(3) << arr[i][j] << "\t";
}
cout << endl;
}
}
int main() {
int row;
int col;
cout << "Please, enter the number of rows of the matrix A: " << endl;
cin >> row;
cout << "Please, enter the number of columns of the matrix A: " << endl;
cin >> col;
IntVec2d arr;
// TASK 1
fillTheMatrix(arr); // No matching function for call to 'fillTheMatrix'
theMatrixView(arr); // // No matching function for call to 'theMatrixView'
}
CodePudding user response:
Leaving out the fact that you're trying to initialize a VLA, your issue comes from the fact that you are trying to pass an int[][]
into a int**
.
It seems you're believing this to be possible due to the fact that an int[]
can be passed to a int*
parameter. but an int[]
!= int*
rather single dimension arrays go through array to pointer decay: In places where a pointer type is expected, an array type will be implicitly converted to a pointer type pointing to the first element of the array, int arr[10]
will be converted to int *arr
with value &(arr[0])
.
In the case of a multidimensional array, array to pointer decay still does the same thing: int arr[10][5]
implicitly converts to: int(*arr)[5]
, with value: &(arr[0])
which is the address of the first element of the first dimension.
As other answers have recommended use std::vector<std::vector<int>> arr
.
All of what i've talked about is explained in more detail here