send a dynamice 3D array to a function in c++ - c++

I am early in c++ programming. I want to send a 3D array to a function.same:
const int MaxNumberOfLegs=function1();
double D_and_L_Of_Legs[4][2][MaxNumberOfLegs] = { { {1, 2, 3.4, 4} , {1, 2, 3, 4} },
{ {1, 2, 3, 4.5} , {1, 2, 3} },
{ {1.8, 2, 3, 4} , {1, 2, 3, 4} },
{ {} , {} }
};
function2(D_and_L_Of_Legs);
and function2 is same:
void ProcessImage(double D_and_L_Of_Legs[4][2][MaxNumberOfLegs]){
}
in my code, MaxNumberOfLegs variable calculate with function1 and not a const variable. and in c++ when we want to send an array we must write dimention of array.
Now my question is, How can i send 3d array when third dimention is not const??

This function will do:
void ProcessImage(double D_and_L_Of_Legs[][][], int MaxNumberOfLegs){
}
And when you want to call, do this:
const int MaxNumberOfLegs=function1();
double D_and_L_Of_Legs[4][2][MaxNumberOfLegs] = {
{ {1, 2, 3.4, 4} ,{1, 2, 3, 4} },
{ {1, 2, 3, 4.5} , {1, 2, 3} },
{ {1.8, 2, 3, 4} , {1, 2, 3, 4} },
{ {} , {} }
};
function2(D_and_L_Of_Legs,MaxNumberOfLegs);
Alternative method:
Try to declare MaxNumberOfLegs out side the function as a global variable and keep all the code same. ie int MaxNumberOfLegs=function1(); put this on the top of the code. and inside the function make MaxNumberOfLegs=function1();.

Related

How does list initialization work? Is there any overloading done?

I came across this type of initialization and was curious to know how it works:
list<int> a = { 1, 2, 3, 4, 5};
This is equivaent to:
b[5] = { 1, 2, 3, 4, 5}
{ 1, 2, 3, 4, 5}
is syntactic sugar for
a[0] = 1 ... a[4] = 5
conversion
a = (list<int>) b

generating a set of sets that appear in every set

I have an array of arrays of things
typedef std::vector<thing> group;
std::vector<group> groups;
things could be compared like so
int comparison(thing a, thing b);
where the return value is 0, 1 or 2
0 means that the things are not alike
1 means that they are alike and a is more specific or equal to b
2 means that they are alike and b is more specific or equal to a
and I am looking for a function that would return me a group that contains all things that appear in every group.
std::getgroup(groups.begin(), groups.end(), myComparisonFunction);
the problem is I have no idea what this function may be called, if it does even exist, or what the closest thing to it would be.
Eventually, what you want is an intersection. Luckily, there is std::set_intersection which almost does what you need. Here's a simple example on std::vector<std::vector<int>>. You can easily change it to work with your thing:
#include <iostream>
#include <vector>
#include <algorithm>
std::vector<int> getGroup(const std::vector<std::vector<int>>& groups) {
std::vector<int> group;
std::vector<int> temp = groups[0];
std::sort(temp.begin(), temp.end());
for ( unsigned i = 1; i < groups.size(); ++i ) {
group = std::vector<int>();
std::vector<int> temp2 = groups[i];
std::sort(temp2.begin(), temp2.end());
std::set_intersection(temp2.begin(), temp2.end(),
temp.begin(), temp.end(),
std::back_inserter(group));
temp = group;
}
return group;
}
int main() {
std::vector<std::vector<int>> groups = { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{1, 2, 3, 5, 6, 7, 8, 10},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{1, 3, 4, 5, 6, 9, 10},
{1, 2, 6, 7, 8, 9, 10},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} };
for ( auto g : getGroup(groups) )
std::cout << g << "\n";
return 0;
}
This will print:
1
6
10

Array too many initializer values

I have a function declaration as follows
void set_values(float values[4][4]);
If I call the function like this everything is OK.
float values[4][4] = {
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 }
};
mat1.set_values(values);
However i thought that I could take the array declared in the curly braces and pass it directly into the function like this:
mat1.set_values({
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 }
});
But this gives me a compile error too many initializer values
Why does the first code work but not the second one?
Your function expects an array object, not an initialization list for such an object.

Having some trouble with initializing a 2D array and then sending it off to a function

I am making a TicTacToe program and I'm trying to use OOP techniques. Within my 'Board' class I am wanting the program to store each way a set of moves can be won.
I hope this can be demonstrated here:
Board.h
#pragma once
class Board
{
private:
int winningRows[8][3]; //Variable in question
public:
static const char X = 'X'; //Game piece 'X'
static const char O = 'O'; //Game piece 'O'
static const char EMPTY = ' '; //Empty game piece
static const char TIE = 'T'; //Game is tie
static const char NOONE = 'N'; //Nobody has won game yet
static const int numbOfSquares = 9; //Number of squares on the board
int InitializeWinningCombinations();
void FindWinner();
};
Board.cpp
#include "stdafx.h"
#include "Board.h"
int Board::InitializeWinningCombinations()
{
/*
The playing board
0, 1, 2
3, 4, 5
6, 7, 8
*/
//All possible ways player can win game
winningRows[8][3] = {
//Horizontal
{0, 1, 2},
{3, 4, 5},
{6, 7, 8},
//Vertical
{0, 3, 6},
{1, 4, 7},
{2, 5, 8},
//Diagonal
{2, 4, 6},
{0, 4, 8}
};
//return winnigRows[8][3];
}
void Board::FindWinner()
{
//I am wanting to get the variable here so I can play around with it later.
int winningRows = InitializeWinningCombinations();
}
I could just have the 'winningRows' variable inside the 'FindWinnner' function but from my understanding it is best to abstract as much as possible and have it as a member of the 'Board' class
Thank you for your time.
winningRows[8][3] = {
//Horizontal
{0, 1, 2},
{3, 4, 5},
{6, 7, 8},
//Vertical
{0, 3, 6},
{1, 4, 7},
{2, 5, 8},
//Diagonal
{2, 4, 6},
{0, 4, 8}
};
Is an attempted array assignment not an initialization and it cannot be done. You can initialize the array in a constructor like
Board() : winningRows{
//Horizontal
{0, 1, 2},
{3, 4, 5},
{6, 7, 8},
//Vertical
{0, 3, 6},
{1, 4, 7},
{2, 5, 8},
//Diagonal
{2, 4, 6},
{0, 4, 8}
} {}
Live Example
You'd have to change the signature to
int** InitializeWinningCombinations();
Then you could call it as
int** winningRows = InitializeWinningCombinations();

How to create a 2D array in C++ using this specific container

I'm trying to port a
int a[][]
from Java to C++. I'm using this class as a container ArrayRef for ints because it handles references, and the project uses it extensively. In the AbstractReader class I declared
const ArrayRef<int> START_END_PATTERN_;
const ArrayRef<int> MIDDLE_PATTERN_;
const ArrayRef<ArrayRef<int> > L_PATTERNS_;
const ArrayRef<ArrayRef<int> > L_AND_G_PATTERNS_;
and
static int START_END_PATTERN[];
static int MIDDLE_PATTERN[];
static int L_PATTERNS[10][4];
static int L_AND_G_PATTERNS[20][4];
Note the trailing underscore to differentiate the two variables.
I'm not sure what to do in order to initialize the two-dimensional ArrayRef. What I'm posting here will segfault because those ArrayRefs are being allocated on the stack. Anybody have a clever way to do this?
The only way I've actually managed to get it to work is using a ArrayRef< Ref<ArrayRef<int> > > by making ArrayRef inherit from Counted, which is basically a class that allows for Reference Counting in C++. But in order to access the elements I hen have to do something like *(foo[i])[j], which is slightly nastier than foo[i][j].
int AbstractReader::L\_AND\_G_PATTERNS[20][4] = {
{3, 2, 1, 1}, // 0
{2, 2, 2, 1}, // 1
{2, 1, 2, 2}, // 2
{1, 4, 1, 1}, // 3
{1, 1, 3, 2}, // 4
{1, 2, 3, 1}, // 5
{1, 1, 1, 4}, // 6
{1, 3, 1, 2}, // 7
{1, 2, 1, 3}, // 8
{3, 1, 1, 2}, // 9
// G patterns
{1, 1, 2, 3}, // 0
{1, 2, 2, 2}, // 1
{2, 2, 1, 2}, // 2
{1, 1, 4, 1}, // 3
{2, 3, 1, 1}, // 4
{1, 3, 2, 1}, // 5
{4, 1, 1, 1}, // 6
{2, 1, 3, 1}, // 7
{3, 1, 2, 1}, // 8
{2, 1, 1, 3} // 9
};
AbstractReader::AbstractReader()
: decodeRowStringBuffer_(ostringstream::app),
START_END_PATTERN_(START_END_PATTERN, 3),
MIDDLE_PATTERN_(MIDDLE_PATTERN, 5),
L_PATTERNS_(10),
L_AND_G_PATTERNS_(20) {
for (int i = 0; i < 20; i++) {
if (i < 10) {
L_PATTERNS_[i] = ArrayRef<int> ((L_PATTERNS[i]), 4);
}
ArrayRef<int> lgpattern((L_AND_G_PATTERNS[i]), 4);
L_AND_G_PATTERNS_[i] = lgpattern;
}
}
What you have should be safe. The (stack allocated) ArrayRefs create heap allocated Arrays to back them, and then share those Arrays.
Edit: Thanks for posting Counted. Took a bit of work, but I think I see what's going on.
Solution: Don't declare L_PATTERNS_ or L_AND_G_PATTERNS_ as const. Alternately, const_cast to get the desired operator[]. E.g.
const_cast<ArrayRef<ArrayRef<int> > &>(L_PATTERNS_)[i] = ArrayRef<int> ((L_PATTERNS[i]), 4);
Rationale:
In AbstractReader, you declare:
const ArrayRef<ArrayRef<int> > L_PATTERNS_;
Then in its constructor, you attempt an assignment:
AbstractReader::AbstractReader() :
{
...
L_PATTERNS_[i] = ArrayRef<int> ((L_PATTERNS[i]), 4);
...
}
Since L_PATTERNS_ is const, L_PATTERNS_[i] invokes a method from ArrayRef<ArrayRef<int> >:
T operator[](size_t i) const { return (*array_)[i]; }
This returns a brand new copy of what was at L_PATTERNS_[i]. The assignment then occurs (into a temporary), leaving the original unchanged. When you later go back to access L_PATTERNS_[xxx], you're looking at the original, uninitialized value (which is a NULL reference/pointer). Thus the segfault.
Somewhat surprising is that ArrayRef even allows this assignment. Certainly it breaks the "Principle of Least Surprise". One would expect the compiler to issue an error. To make sure that the compiler is more helpful in the future, we need to give a slightly different definition of ArrayRef's operator[] const (Array.h:121), such as:
const T operator[](size_t i) const { return (*array_)[i]; }
or perhaps (with caveats):
const T& operator[](size_t i) const { return (*array_)[i]; }
After making either change, the compiler disallows allow the assignment. GCC, for example, reports:
error: passing 'const common::ArrayRef<int>' as 'this' argument of 'common::ArrayRef<T>& common::ArrayRef<T>::operator=(const common::ArrayRef<T>&) [with T = int]' discards qualifiers
Causes may be several. For instance, you don't include in your paste the "Counted" class, and at some point, a->retain() is called (line 130). This method is not shown.