Cant's pass a 2D array to a function in C++ - c++

I was following internet tutorials on this topic, but I have the following situation:
I have a function with the following signature:
void func(long& rows, long& columns, int array[][columns]);
and I'm trying to use the function like this:
int matrix[5][4] = {0, -1, 2, -3,
4, -5, 6, -7,
8, -9, 10, -11,
12, -13, 14, -15,
16, -17, 18, -19};
long rows = 5;
long columns = 4;
func(rows, columns, matrix);
^--- 'No matching function for call to 'func''
What is the problem? Why can't it call the function?

Variable length arrays is not a standard C++ features.
You could declare the function and the array the following way
const size_t columns = 4;
void func( size_t rows, const int array[][columns]);
//...
int matrix[][columns] = { { 0, -1, 2, -3 },
{ 4, -5, 6, -7 },
{ 8, -9, 10, -11 },
{ 12, -13, 14, -15 },
{ 16, -17, 18, -19 } };
func( sizeof( matrix ) / sizeof( *matrix ), matrix);
//...
void func( size_t rows, const int array[][columns] )
{
std::cout << rows << columns << array[0][1];
}
Pay attention to that as the number of columns is well-known there is no sense to pass it to the function. And moreover there is no sense to pass the number of rows and columns by reference.

Have you actually defined func in your program?
The following source code compiles and works fine for me
#include <iostream>
#define ROW 5
#define COLUMN 4
void func(long &rows, long &columns, int array[][COLUMN]);
int main()
{
int matrix[ROW][COLUMN] = {0, -1, 2, -3,
4, -5, 6, -7,
8, -9, 10, -11,
12, -13, 14, -15,
16, -17, 18, -19};
long rows = 5;
long columns = 4;
func(rows, columns, matrix);
return 0;
}
void func(long &rows, long &columns, int array[][COLUMN])
{
std::cout << rows << columns << array[0][1];
}

Related

How to swap rows inside a matrix according to the values of a certain column in ascending order in c++

I am having trouble swapping rows inside a Matrix (nested array) according to the value of a specific column, I am making a console application that displays the results of a group stage in the football world cup so first I insert the results of the games to update the statistics of each team (rows) and generate the input array, but finally, I need to sort the rows according to the number of points of each team (the last position in each row). I need to create a function to generate the output array.
Input array:
inputArray[4][7] {
{0, 2, 1, 1, 3, -2, 2},
{1, 1, 1, 3, 3, 0, 4},
{2, 0, 1, 3, 1, 2, 6},
{1, 1, 1, 2, 2, 0, 4},
}
Output array of the function:
outputArray[4][7] {
{2, 0, 1, 3, 1, 2, 6},
{1, 1, 1, 3, 3, 0, 4},
{1, 1, 1, 2, 2, 0, 4},
{0, 2, 1, 1, 3, -2, 2},
}
The solution is straightforward. But my guess is that this is not what you want.
And, I think that the last value in the row is not the sum . . .
But let us first look at one potential solution:
#include <iostream>
#include <algorithm>
#include <array>
constexpr size_t NumberOfRows = 4u;
constexpr size_t NumberOfColumns = 7u;
using Columns = std::array<int, NumberOfColumns>;
using Array = std::array<Columns,NumberOfRows>;
int main() {
Array array{{ {0, 2, 1, 1, 3, -2, 2},
{1, 1, 1, 3, 3, 0, 4},
{2, 0, 1, 3, 1, 2, 6},
{1, 1, 1, 2, 2, 0, 4} }};
std::sort(std::begin(array), std::end(array), [](const Columns& c1, const Columns& c2) {return c1[6] < c2[6]; });
for (const Columns& c : array) {
for (const int i : c) std::cout << i << '\t';
std::cout << '\n';
}
}
If you want the array to be dynamic, then you may use a std::vector instead. You can then resize the number of rows and then number of columns.
#include <iostream>
#include <algorithm>
#include <vector>
constexpr size_t NumberOfRows = 4u;
constexpr size_t NumberOfColumns = 7u;
using Columns = std::vector<int>;
using Array = std::vector<Columns>;
int main() {
Array array{ {0, 2, 1, 1, 3, -2, 2},
{1, 1, 1, 3, 3, 0, 4},
{2, 0, 1, 3, 1, 2, 6},
{1, 1, 1, 2, 2, 0, 4} };
std::sort(std::begin(array), std::end(array), [](const Columns& c1, const Columns& c2) {return c1[6] < c2[6]; });
for (const Columns& c : array) {
for (const int i : c) std::cout << i << '\t';
std::cout << '\n';
}
}
But I still think that this is the wrong design. Becuase the last value in a row is the sum of other values. It is dependent, can be calculated, and there is no need to store ist.
See the following better design:
#include <iostream>
#include <algorithm>
#include <vector>
#include <numeric>
struct Result {
std::vector<int> values{};
int sum() const { return std::accumulate(values.begin(), values.end(), 0); }
friend std::ostream& operator << (std::ostream& os, const Result& r) {
for (const int i : r.values) os << i << '\t';
return os << "--> " << r.sum();;
}
};
struct Series {
std::vector<Result> results{};
friend std::ostream& operator << (std::ostream& os, const Series& s) {
for (const Result r : s.results) os << r << '\n';
return os;
}
};
int main() {
Series series{{
{{0, 2, 1, 1, 3,-2}},
{{1, 1, 1, 3, 3, 0}},
{{2, 0, 1, 3, 1, 2}},
{{ 1, 1, 1, 2, 2, 0}}
}};
std::sort(series.results.begin(), series.results.end(), [](const Result& r1, const Result& r2) {return r1.sum() < r2.sum(); });
std::cout << series;
}
But you did not give enough information to give a good answer.

Pass two dimensional array in function [duplicate]

This question already has answers here:
How to pass a 2D array by pointer in C?
(5 answers)
Closed 2 years ago.
I am trying to pass two dimensional array in function, but is has two errors which I don't know why. I have some articles about passing two dimensional array in function but also can't understand why I fail.
#include <iostream>
using namespace std;
// prototypes
void matrixSwap(double** matrix, int rows, int columns);
int main()
{
const int ROWS = 5;
const int COLUMNS = 5;
double matrix[ROWS][COLUMNS] =
{
{ 1, 2, 3, 4, 5},
{ 6, 7, 8, 9, 0},
{11, 12, 13, 14, 15},
{16, 17, 18, 19, 20},
{21, 22, 23, 24, 25}
};
matrixSwap(matrix, ROWS, COLUMNS);
/* it says
1) argument of type "double (*)[5U]" is incompatible with parameter of type "double **"
2) 'void matrixSwap(double *[],int,int)': cannot convert argument 1 from 'double [5][5]' to 'double *[]'
*/
}
void matrixSwap(double** matrix, int rows, int columns) {}
The multidimensional double array matrix you're trying to pass in the function matrixSwap() to the argument double**, actually doesn't represents a multidimensional array.
Use arrays correctly as shown:
#include <iostream>
using namespace std;
const unsigned short MAXROWS = 5;
// prototypes
void matrixSwap(double matrix[][MAXROWS], int rows, int columns);
int main()
{
const int ROWS = 5;
const int COLUMNS = 5;
double matrix[ROWS][COLUMNS] =
{
{ 1, 2, 3, 4, 5},
{ 6, 7, 8, 9, 0},
{11, 12, 13, 14, 15},
{16, 17, 18, 19, 20},
{21, 22, 23, 24, 25}
};
matrixSwap(matrix, ROWS, COLUMNS);
}
void matrixSwap(double matrix[][MAXROWS], int rows, int columns) {}
Just changed into [][MAXROWS] where MAXROWS contains an unsigned integer of value 5.
The declaration:
void matrixSwap(double matrix[][MAXROWS], int rows, int columns)
is equivalent to:
void matrixSwap(double (*matrix)[MAXROWS], int rows, int columns)
Notice that here I've used *matrix and then appended [MAXROWS] which does the same job as matrix[][MAXROWS].
So you may do the same thing in another way as follows:
void matrixSwap(double (*matrix)[MAXROWS], int rows, int columns) {
for (int i = 0; i < columns; i++) {
for (int j = 0; j < rows; j++) {
std::cout << matrix[i][j] << ' ';
}
std::cout << std::endl;
}
}
This will give you the output:
1 2 3 4 5
6 7 8 9 0
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
To see if the matrix is successfully passed into the function by the new argument.

Char Point Memory Allocation to reference address of C++ String?

I would like to convert an array of Integers
2, 3, 4, 8
5, 7, 9, 12
1, 0, 6, 10
to a string with the entries of that matrix appended in clockwise order
“2, 3, 4, 8, 12, 10, 6, 0, 1, 5, 7, 9”.
I have to keep declaration of int * Matrix and char * OutBuffer the way they are
int main()
{
int matrixArray[rowCount][columnCount] =
{ {2, 3, 4, 8},
{5, 7, 9, 12},
{1, 0, 6, 10}};
int * matrix;
string prebuffer;
char * outBuffer;
outBuffer = new (nothrow) char[24];
matrix = &matrixArray[0][0];
BuildStringFromMatrix(matrix, rowCount, columnCount, outBuffer);
}
I declare and address all my pointers before passing them in. However, I am not sure if I am going about allocating memory for the outBuffer to store the characters of prebuffer correctly?
void BuildStringFromMatrix(int* Matrix, int NumRows, int NumColumns, char * OutBuffer)
{
string prebuffer;
bool stringLeft = true;
int i = 0;
while (stringLeft)
{
int clockwiseDir[12] = { 1,1,1,4,1,1,0,4,-4,-1,-1,-1 };
prebuffer = to_string(Matrix[i]) + ", ";
OutBuffer = new char [prebuffer.length() + 1];
cout << prebuffer;
i += clockwiseDir[i];
if (i == 6)
{
prebuffer = to_string(Matrix[i]) + " ";
cout << prebuffer;
stringLeft = false;
}
}
}
**When I do not implement OutBuffer I have no trouble accessing and printing the matrix in clockwise format
But I how would I go about using OutBuffer to reference and print prebuffers contents??
I need numbers to display not unprintable symbols on the ASCII table
Thanks in advance :)
**
Firstly, in your loop under BuildStringFromMatrix function you are not using your i value anywhere.
Second, matrix = matrixArray should do fine.

Declare and initialize a map type matrix separately in EIGEN

I am trying to use Eigen:Map with Stride to map two matrices to an array. For example, if
arr = {1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20 ,21 ,22 ,23 ,24}
I want the mapped matrices to be
mat1 = {1, 7, 13, 19;
3, 9, 15, 21;
5, 11, 17, 23}
and
mat2 = {2, 8, 14, 20;
4, 10, 16, 22;
6, 12, 18, 24}
The following code works:
int nmat = 2; // number of matrices
int nrow = 3; // number of rows for each matrix
int ncol = 4; // number of columns for each matrix
int arr_size = nmat*nrow*ncol; // size of the array.
int *arr = new int[arr_size];
Map<MatrixXi, 0, Stride<Dynamic, Dynamic> > mat1(arr ,nrow, ncol, Stride<Dynamic,Dynamic>(nrow*nmat, nmat));
Map<MatrixXi, 0, Stride<Dynamic, Dynamic> > mat2(arr+1 ,nrow, ncol, Stride<Dynamic,Dynamic>(nrow*nmat, nmat));
for (int i=0; i<arr_size; i++) {
arr[i] = i+1;
}
cout <<"mat1 = \n"<<mat1<<endl;
cout <<"mat2 = \n"<<mat2<<endl;
The results are:
mat1 =
1 7 13 19
3 9 15 21
5 11 17 23
mat2 =
2 8 14 20
4 10 16 22
6 12 18 24
However, I would like to declare and map the matrices separately like the following code:
MatrixXi mat1;
MatrixXi mat2;
new(&mat1) Map<MatrixXi, 0, Stride<Dynamic, Dynamic> > (arr ,nrow, ncol, Stride<Dynamic,Dynamic>(nrow*nmat, nmat));
new(&mat2) Map<MatrixXi, 0, Stride<Dynamic, Dynamic> > (arr+1 ,nrow, ncol, Stride<Dynamic,Dynamic>(nrow*nmat, nmat));
This will give me Segmentation fault.
If I comment out mat2 like the code below:
MatrixXi mat1;
// MatrixXi mat2;
new(&mat1) Map<MatrixXi, 0, Stride<Dynamic, Dynamic> > (arr ,nrow, ncol, Stride<Dynamic,Dynamic>(nrow*nmat, nmat));
// new(&mat2) Map<MatrixXi, 0, Stride<Dynamic, Dynamic> > (arr+1 ,nrow, ncol, Stride<Dynamic,Dynamic>(nrow*nmat, nmat));
Then there is no Segmentation fault, but the Stride is not working. The results are:
mat1 =
1 4 7 10
2 5 8 11
3 6 9 12
The reason I want to separate the declaration and initialization is that I want to write a class which mat1 and mat2 are members of it.
You mat1 and mat2 are of the type Map<MatrixXi, 0, Stride<Dynamic, Dynamic> >, but when you do it separately, you defined them as MatrixXi.
If you want them as a class member, you could follow the general way for an class member object.
class MyClass {
MyClass(int* arr, int nrow, int ncol, int nmat) :
a(3), v(10),
mat1(arr, nrow, ncol, Stride<Dynamic, Dynamic>(nrow * nmat, nmat)),
mat2(arr + 1, nrow, ncol, Stride<Dynamic, Dynamic>(nrow * nmat, nmat)) {
}
int a;
std::vector<int> v;
Map<MatrixXi, 0, Stride<Dynamic, Dynamic> > mat1;
Map<MatrixXi, 0, Stride<Dynamic, Dynamic> > mat2;
};
the new operator is not needed.

Calculating both weighted and unweighted statistics with the same boost::accumulator_set?

With Boost's accumulators I can easily calculate statistical quantities for
weighted or unweighted input sets. I wonder if it is possible to mix weighted
and unweighted quantities inside the same accumulator. Looking at the
docs it doesn't seem that way.
This compiles fine but produces another result than I would have liked:
using namespace boost::accumulators;
const double a[] = {1, 1, 1, 1, 1, 2, 2, 2, 2};
const double w[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
accumulator_set<double, features<tag::sum, tag::weighted_sum>, double> stats;
for (size_t i=0; i<9; ++i)
stats(a[i], weight = w[i]);
std::cout << sum(stats) <<" "<< weighted_sum(stats) << std::endl;
// outputs "75 75" instead of "13 75"
Also, with a third template parameter to accumulator_set I always seems to
get weighted quantities, even when using an "unweighted" feature and extractor:
accumulator_set<double, features<tag::sum>, double> stats;
for (size_t i=0; i<9; ++i)
stats(a[i], weight = w[i]);
std::cout << sum(stats) << std::endl;
// outputs "75" instead of 13
Do I always have to use two different accumulators if I want to calculate both
weighted and unweighted quantities?
EDIT
I just use sum as an example, in reality I am interested in multiple, more complicated quantities.
It does say in the documentation that
When you specify a weight, all the
accumulators in the set are replaced
with their weighted equivalents.
There are probably better ways to do it but you can try something like this (basically swapping the meaning of the value with that of the weight):
accumulator_set< double, stats< tag::sum, tag::sum_of_weights >, double > acc;
const double a[] = {1, 1, 1, 1, 1, 2, 2, 2, 2};
const double w[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for( int i = 0; i < sizeof( a ) / sizeof( a[ 0 ] ); i++ )
acc( w[ i ], weight = a[ i ] );
std::cout << extract_result< tag::sum >( acc ) << std::endl; // weighted sum, prints 75
std::cout << extract_result< tag::sum_of_weights >( acc ) << std::endl; // sum, prints 13