Passing three dimensional array by reference in c++ - c++

Function is defined as:
int strip(double *signalstnV){
.
.
return 0;
}
And main function it is called as:
main{
.
.
double signalstnV[iteration][2*range+1][3];
.
.
check = strip(signalstnV);
.
}
I wanted to use the array in next function in main after it is modified in strip function. But during compilation i am getting an error as following
sim.C: In function ‘int main(int, char**)’:
sim.C:54:26: error: cannot convert ‘double ()[151][3]’ to ‘double’ for argument ‘1’ to ‘int strip(double*)’
check = strip(signalstnV);
I am not able to understand it. Please help.
My main goal is to generate array from strip function and pass it to other functions later in code.
Also when i used this array in another function
threshold(double * signalstnV)
and using a for loop to extract some specific values, it gives error as:
invalid types ‘double[int]’ for array subscript
if (signalstnV[k][j][3] < -0.015){
..}

An ordinary single-dimensional array decays to a pointer to its first value. A multi-dimensional array decays only in its first dimension, decaying to a pointer to the initial 2nd dimension of the array.
If you wish to "super-decay" a multi-dimensional array to a pointer to its first value, then simply do that yourself:
check = strip(&signalstnV[0][0][0]);

For such cases, with more or less complicated types - use type aliases:
//double signalstnV[iteration][2*range+1][3];
using IterationValues = double[iteration];
using IterationRangesValues = IterationValues [2*range+1];
//...
then, it is obvious that calling this:
IterationRangesValues signalstnV[3];
check = strip(signalstnV);
You need this signature: strip(IterationRangesValues * matrix) or this strip(IterationRangesValues (& matrix)[3]). Of course for this last array you might use typedef too.
You might also use std::array:
using IterationValues = std::array<double, iteration>;
using IterationRangesValues = std::array<IterationValues, 2*range+1>;
//...

To pass the array by reference, one way is:
template<size_t X, size_t Y, size_t Z>
int strip( double(&strip)[X][Y][Z] )
{
}
Then you can call it with various sizes of array.
If you only need to support the one size, then remove the template line and replace X Y Z with the actual dimensions you need to support.

Related

What is an elegant solution to this error from std::find?

I have a class which contains an array which size is unknown at compile time. The array is initialized in the constructor. Then, I have another function that checks if an element is in the array:
class myClass
{
int tab[];
public:
myClass(int array[], int length)
{
std::copy(array, array + length, tab)
}
void myFunction()
{
int x = 8;
int *ptr = std::find(std::begin(tab), std::end(tab), tdc_x);
if (ptr) /* here goes my code */
}
};
I got the following error:
error: no matching function for call to ‘begin(int [0])’
What's wrong with the above piece of code? I know that I can't use std::find with pointers, but my array is an array, not a decayed pointer.
I followed this example. I also included the algorithm header. What am I doing wrong?
I compile my code in C++11.
Edit: I get it now. But how can I do what I want to do in an elegant way?
If I use a pointer instead of the empty array, I won't be able to use std::find.
if I give my array an arbitrary size, I won't be able to copy a bigger array.
What should I do?
int tab[];
The standard doesn't allow empty arrays, but some compilers do as an extension. That doesn't make it legit tho.
If I use a pointer instead of the empty array, I won't be able to use std::find.
Not true, you can still use std::find (s is the size of your tab array).
int *ptr = std::find(tab, tab + s, tdc_x);
if I give my array an arbitrary size, I won't be able to copy a bigger array. What should I do?
Use a std::vector<int>, then call resize()

error : no match for 'operator[]'

I am solving a problem in which I m trying to pass address a 2-D array of a structure and trying to manipulate it but, whenever I use [] operator to access the array elements , I get a compile time error:
no match for 'operator[]'
in my codeblocks IDE.
#include <iostream>
using namespace std;
typedef struct mat
{
int data;
int flag;
} cell;
int mat(cell *);
int main()
{
int m,n;
cin>>m>>n;
cell game[n][m];
cout<<"The length of matrix is "<<mat(&game[0][0]);
}
int mat(cell *arr)
{
return (sizeof(arr[0])/sizeof(arr[0][0]));
}
cell game[n][m];
This is not legal C++. You are using a compiler-specific extension. At this point I advise you against using any compiler-specific extensions. Use standard C++ only. In standard C++ there are no Variable Length Arrays. Don't use arrays in your C++ programs. To get proper variable length array functionality. You should use std::vector instead, like this:
std::vector<std::vector<cell>> game;
Further,
&game[0][0]
is not an address of a 2D array. This is an address of the first element in the array. It contains no information about the number of elements. It is lost forever. You cannot pass it to some function and expect the size of the array to be recovered. To get proper array functionality with a built-in size function, use std::vector.
Last but not least,
(sizeof(arr[0])/sizeof(arr[0][0]));
arr is a cell*. arr[0] is a cell. arr[0][0] is invalid because a cell is neither an array not a pointer, nor it has a custom [] operator defined. In any case you cannot use sizeof to recover the number of elements in the array from a pointer to its first element. To get proper array functionality with a built-in size function, use std::vector.
Two things:
Your function takes a pointer to cell but since you're treating it like a 2D array, you should probably change your signature to either accept a cell ** arr or a cell arr[m][] where m is the (fixed) size of the array and must be specified. Note that these data structures have fundamentally different representations in memory - they just have the same [][] syntax for accessing elements.
You can't use the sizeof function to determine the length of an array if you pass it as a pointer to an elem. You will need to pass the dimensions along with your array, like this:
int mat(cell **arr, int m, int n);
The definition being given basically says that your class doesn't define the operator [], meaning you can't use the syntax you are trying to use.

C++ and recursion with arrays

I've programmed with other languages, but now that I am learning C++, I've found a problem. I am trying to solve a problem with recursion, with a method that takes an array as an argument. I thought about using a public array, maybe, but I can't use the array either way.
From what I've read, it seems to me that it has something to do with the memory. (I thought that, even though it consumes a lot of memory, creating it again with each call would work.)
Here's some code:
static void FindSolution(int row, int column, bool answer[][8][8]) {
for(int i = 0; i < 8; i++)
//Some processing…
bool temp = true;
FindSolution(0, column + 1, answer[row][column] = temp);
}
}
How do I get to actually use the array? Somehow.
The error:
error: array type 'bool [8]' is not assignable
FindSolution(0, column + 1, answer[row][column] = temp);
You have an extra [] on your array. You've declared it as a 3D array, but then you try to assign to it like it is a 2D array. The compiler gets upset because you try to assign a bool value to an array, which is exactly what you are doing:
answer[row][column] = temp;
temp has type bool, but answer[row][column] has type bool[8].
Instead declare the argument without the extra []:
static void FindSolution(int row, int column, bool answer[8][8]) {
You keep incrementing 'column', but you never check it to make sure it doesn't reach 8. When it does reach 8, you're off the end of the array, and you get an error.
There are a few immediate problems with this.
First Problem: Function signature is incorrect
You've declared the third parameter as a 3-dimensional array, but you only want to deal with two dimensions it seems. There are a couple of ways you can redeclare this function to accept a 2D array, for all the options see the accepted answer here. Personally, in this situation I'd go with a template option unless there is a specific reason not to. Something like the following:
template<size_t _rows, size_t _columns>
static void FindSolution(int row, int column, bool (&answer)[_rows][_columns]) {
// todo: Some processing...
}
This allows you to accurately know the size of the array at compile time, of course this won't work so well with dynamically allocated arrays but seeing as you seemed to know the dimensions of the array already at compile time, I figured this wasn't an issue. If it is, check the other ways of passing a 2D array to a function in the link I attached.
Second issue: Recursive call
The second issue is how you're doing your recursive call.
FindSolution(0, column + 1, answer[row][column] = temp);
The result of the assignation of temp to the specific location in the answer array is not the answer array, but rather the value of temp. Effectively the following statement:
answer[row][column] = temp
Is trying to pass a single bool value as a 2-dimensional array, which won't work. In order to correctly call the method again you'll need to do your assignation of temp to the answer array, then call the function again.
answer[row][column] = temp;
FindSolution<_rows,_columns>(0, column + 1, answer);
Should work fine. (Note the explicit template arguments here <_rows,_columns>, this is only needed if you're using the function signature I posted above which made use of templates)

Declaring char[][512]?

I have an C++ SDK that requires a char[][512] as a parameter. I know that this is supposed to be a list of file names and the number of files could vary. For the life of me I cannot figure out how to declare this. I have an array of CStrings and I am trying to copy them over using strcpy_s and then pass them into the SDK. Any idea on how to do this?
This declaration has a special meaning when used to declare parameter of a function. Within the parameter list it is equivalent to char[100][512], char[123][512], char[3][512] (you get the idea - the first size can be just anything, it is simply ignored) and also to char (*)[512]. Effectively, it will accept as an argument a 2D array of chars with flexible (arbitrary) first size.
The array that you will actually pass to this function should be declared with a concrete first size, for example
char names[3][512] = { "abc", "cde", "fgh" };
if you know the first size at compile time, of course.
If the first size is only known at run time (say, n), you'll have to allocate the array dynamically
char (*names)[512] = new char[n][512];
// Now fill it with names
or, more elegantly, with a typedef
typedef char TName[512];
TName* names = new TName[n];
// Now fill it with names
I expect that the SDK function you are talking about also asks you to pass the first size of the name array as another parameter.
It means 2D array of char. The number of rows could vary, and it should/may be specified in another parameter. C/C++ compilers need to know the number columns when a 2D arrays is passed ,So they can build the mapping function. Simply because arrays decay to pointers when they are passed as parameters, size information is lost. For example:
void fun(char matrix[][512], int rows);
...
char matrix[100][512];
...
fun(matrix, 100);
The mapping function that the compiler construct for a 2D array is similar to:
// arrays in C/C++ are stored in Row-Major Order
matrix[i][j] == matrix[i*numberOfColumns + j]
As you can see, when a 2D array is passed and the size information is lost, we need only the number of columns to index any element in this array.
Here is a way to convert an argv-style array of filenames into the form your SDK needs.
typedef char Char512[512];
Char512 * convert(const char *names[], int n)
{
Char512 * arr;
arr = new char[n][512];
for (int i = 0; i < n; n++)
::strncpy(arr[i], names[i], 512);
return arr;
}
When in doubt, use a typedef.
Just a reminder, if you new[] something, you must delete[] (not delete) it sometime.

C++ Inserting 2D array Object into another 2D array Object

In using Dev C++, I a m trying to insert a smaller 2D array object into a larger 2D array object. While attempting to achieve that, I came into compilers errors which I do not know how to solve.
I attempt to insert the smaller Object by making it returning the array's name. Then I attempt to change the values inside the large array with the values of the smaller array.
There two line of code that I have problems with:
int result = smallerArray.extractPiece();
largerArray.extractArray(result);
And within these two lines of codes:
int Piece::extractPiece()
{
return **pieceArray;
}
and
void Grid::extractArray( int** arr )
{
for(int i = 0; i &lt xGrid ; ++i)
{
for (int j = 0; j &lt yGrid ; ++j)
{
squares[i][j] = arr[i][j];
}
}
}
The two of the problems is that "int result" will not hold smallerArray.extractPiece(),
and if i just put "smallerArray.extractPiece()" in largerArray.extractArray(), i still get problems. I attempted to make "int result" a pointer pointer, as "int** result", i still have the same errors.
These are the errors that i get when i try to compile in Dev C++:
In function `int main()';
invalid conversion from `int' to `int**'
initlizing argument 1 of 'void Grid::extractArray(int**)'
[Build Error] [grid test.o] Error 1
Does anyone know whats wrong?
It's precisely this bunch of code:
int result = smallerArray.extractPiece();
largerArray.extractArray(result);
// ...
int Piece::extractPiece() {
return **pieceArray;
}
Trying to pass an int to extractArray, which wants a pointer to a pointer, presumable your dynamic array, and not an int. Try changing it to
int **result = smallerArray.extractPiece();
largerArray.extractArray(result);
// ...
int ** Piece::extractPiece() {
return pieceArray;
}
Only changing result to a pointer to pointer won't work. You of course also have to change what extractPiece returns (changing from int to int**)
Look, always at least for me it was easier to manage 2D arrays internally as 1D arrays where M[i,j]=A[i*N+j] where N is the number of cols (or rows, if the 2D arrays is row-column type). Users may get elements with the i,j indices but my class always store A[M * N] as private data. Passing 1-D pointer arrays is easier than managing 2-D pointer arrays (you can't fall in the pointer-to-pointer syntax which can get messy in some code).,
This is not related to this question, but since I don't know about specific compiler optimization instrinsics, I wonder if M[i,j] gets transformed to A[i] internally to use simpler addressing modes in the generated code.