2 dimensional arrays passed to a function in c++ - c++

I'm working on doing calculations in a two dimensional array
but keep getting a nasty error.
i call the function by :
if(checkArray(array))
and try to pass it in like this:
bool checkArray(double array[][10]) //or double *array[][10] to no avail
the error is
error: cannot convert ‘double ()[(((unsigned int)(((int)n) + -0x00000000000000001)) + 1)]’ to ‘double’ for argument ‘1’ to ‘bool checkArray(double*)’
code snippet
//array declaration
int n = 10;
double array[n][n];
//function call to pass in array
while(f != 25)
{
cout<<endl;
cout<<endl;
if(checkArray(array)) //this is the line of the error
{
cout<<"EXIT EXIT EXIT"<<endl;
}
f++;
}
//function declaration
bool checkArray(double *array)//, double newArray[][10])
{
double length = sizeof(array);
for(int i = 0; i < length; i++)
for(int j = 0; j < length;j++)
{
double temp = array[i][j];
}
}

When I look at the error you are getting, I have an impression that your function has got invalid declaration. It looks like as if it would expect only one-dimensional array: double*.
However, your question seems a little unclear for me... Could you paste the function code?

Is this really a direct (if edited) copy of your code?
This line:
int n = 10; double array[n][n];
is not valid C++. You can't declare an array with variable dimensions. This would work:
const int n = 10; double array[n][n];
You want to declare checkArray as:
bool checkArray(double array[][10])
and you absolutely do not want to do this:
double length = sizeof(array);
because that will assign to length the size of a pointer, in bytes (4 or 8.) You need to pass in the number of rows explicitly. Also, you're much better off declaring length as an int, or better yet a size_t.
This seems like a decent resource: http://www.fredosaurus.com/notes-cpp/arrayptr/22twodim.html

Related

Variable not initialized with a constant expression

I'm a novice programmer who is learning C++.
Below are the relevant parts of my code. VSCode throws an error 'size' not initialized with a constant expression, and I'm unclear about the underlying error(s) in which I'm making.
int min, max;
min = max = 0;
for(int i=0;i<a.size();i++){
if(a[i]/int(pow(10,exp))%10>max) max = a[i];
if(a[i]/int(pow(10,exp))%10<min) min = a[i];
}
return std::array<int,2> {min,max};
}
std::vector<int> radixSort(std::vector<int> a){
int xp,maxval;
xp = maxval = 0;
int xpv = pow(10, xp);
for(int i=0;i<a.size();i++){
if(a[i]>maxval) maxval = a[i];
}
while(maxval/pow(10/xp) != 0){
std::array<int, 2> rg = findRange(a,xp);
int min = rg[0];
int size = rg[1]-rg[0]+1; //error at rg[1]: attempt to access storage one position past the end of an array of 1 elements
std::array<int,size> count;// Variable size cannot be used as constant
...
I'd like to clarify a few details:
I've returned an array size 2 with 2 elements {max,min} from my function findRange. So why is it that the compiler only interprets it as one? Changing the function return type to std::vector doesn't seem to fix the problem.
I realized that array sizes need to be fixed at compile time, but when I put const or constexpr infront of a size variable it doesn't fix the problem.
Feel free to point out any other mistakes in my code. Thanks!
EDIT: Changed int i to int i=0 in the first for loop
it is just because of array of size 2 with 2 elements try it with inheritance concept

Why am I getting the Invalid conversion from 'int' to 'int*' error among other errors?

So I'm very new to pointers and pointer syntax, and I've just written this function but have about 5-6 build errors and after looking at the code for a while, I'm still unsure on how to fix them or why they are errors. I'm new to pointers and memory so that is why I am unsure regarding how to fix these bugs and why they are wrong. Thanks for your help it is appreciated it!
int makeFrequency (int data[], int dSize, int *minDataValue, int *maxDataValue)
{
findMinAndMax(data, dSize, minDataValue, maxDataValue);
int fSize = *minDataValue + *maxDataValue; // invalid operands of types 'int' and 'int*' to binary 'operator+' error?
int frequency = new int [fSize]; //invalid conversion error?
if (frequency == NULL)
{
return NULL;
}
for (int i = 0; i <= fSize; i++)
{
frequency[i] = 0; // invalid types 'int[int]' for array subscript error?
}
for (int i = 0; i <= dSize; i++)
{
int j = data[i] - (*minDataValue)+1; // invalid operands of types 'int' and 'int*' to binary 'operator-' error?
frequency[j] = frequency[j] + 1; // invalid types 'int[int]' for array subscript error?
}
return frequency;
}
int main() {
int dSize;
int *ArrayOfInts;
cout << "How many data values? ";
cin >> dSize;
ArrayOfInts = new int [dSize];
getData(dSize, ArrayOfInts);
int *frequency, min, max;
frequency = makeFrequency (ArrayOfInts, dSize, &min, &max); // invalid conversion error?
if (frequency == NULL) return -1;
makeHistogram(frequency, min, max);
delete [] frequency;
return 0;
}
int frequency = new int [fSize]; //invalid conversion error?
new returns a pointer to the heap-allocated object. When you allocate X, new return an X *.
new X[n] allocates n instances of X and returns a pointer to the first instance of X.
(In all cases, new also invokes the allocated objects' constructors, but this is an irrelevant point here).
new int [fSize];
Therefore, this expression returns an int *.
int frequency
frequency is, obviously an int.
int frequency = new int [fSize];
Putting all of the above together, here you are attempting to assign an int * to an int. That's your conversion error. frequency should be declared as an int *.

How to modify and pass array pointer as argument to a function which require array as argument?

This probably is a beginner question. Say for example, in the following method we use the arrays alpha and theta, which are passed as argument to the function gsl_ran_dirichlet, and the function computes new theta values and updates the same array theta.
Now, the problem is that I will not be able to initialize theta in a class as provided in the following code piece. Rather I will have to use pointers to arrays theta and alpha. How will I pass these array pointers as argument to the method gsl_ran_dirichlet?
I know it is not possible to pass pointer as argument to method which require array as argument. But what is the best way to accomplish this (assume we cannot modify gsl_ran_dirichlet)?
void test (){
double alpha[2] = { 1, 1};
double theta[2] = { 1, 1};
const gsl_rng_type * T;
gsl_rng * r;
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc(T);
gsl_ran_dirichlet(r, 2, alpha, theta);
cout << theta[0] << "," << theta[1] << endl;
gsl_rng_free(r);
}
Result:
0.4,0.6
Now, I am also adding the function and the error I get in the following code, where the arrays are loaded dynamically:
void test() {
double *alpha, *theta;
alpha = new double[3];
theta = new double[3];
for(int i=0; i<3; ++i){
alpha = 1;
theta = 1;
}
const gsl_rng_type * T;
gsl_rng * r;
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc(T);
gsl_ran_dirichlet(r, 3, alpha, theta);
cout << theta[0] << "," << theta[1] << "," << theta[2] << ":";
gsl_rng_free(r);
}
Error:
../test.cpp:56:11: error: invalid conversion from ‘int’ to ‘double*’ [-fpermissive]
../test.cpp:57:11: error: invalid conversion from ‘int’ to ‘double*’ [-fpermissive]
make: *** [test.o] Error 1
General:
Variable to pointer: &variable.
Pointer to variable: *pointer.
Specific:
The name of an array and a pointer to an array can be used in the same way, i.e. theta[0] and pointer_to_theta[0] are equivalent.
int foo[2] = { 1, 2 };
int * pointer_to_foo = foo;
assert( foo[1] == pointer_to_foo[1] );
Your problem is not about calling a function.
it is simply that your
for(int i=0; i<3; ++i){
alpha = 1;
theta = 1;
}
is wrong.
alpha is a double* which you cannot assign a int (1) to it.
What you are trying to do is
alpha[i] = 1;
or
*(alpha + i) = 1
And! please learn the read the error message. There is a line number in the error message and it is pointing you to where the problem is happening. You should be able to find it by yourself if you look into your line 56 and 57
Try changing the assignments in your for loop into
alpha[i] = 1;
theta[i] = 1;
double* alpha;
double* tetha;
void foo()
{
double (&refToAlpha)[2] = reinterpret_cast<double(&)[2]> (alpha);
double (&refToTetha)[2] = reinterpret_cast<double(&)[2]> (tetha);
...
gsl_ran_dirichlet(r, 2, refToAlpha, refToTetha);
}
The compilation error is simple: you assign an int to a pointer-to-a-double.
for( int i=0; i < 3; ++i ) {
alpha[i] = i; // dereference before assignment
}
The 'how-to-pass-an-array' to a function is somewhat more complicated. It's common for legacy and C-compatible code to pass in the pointer to the array, together with it's size (foo( int* values, size_t size)).
If you have the freedom of choice, you would prefer the use of standard collections (i.e. a std::vector<double>) (and algorithms like iota):
std::vector<double> alpha, theta;
std::iota(begin(alpha), end(alpha));
std::iota(begin(theta), end(theta));
and pass the collections by const reference if you want the function to read them, by value if you want the function to own a copy, by reference if you want the function to change the argument (i.e. an output argument).
void gsl_ran_dirichlet(
std::vector<double> &r, // though I prefer output args to come last
int i,
const std::vector<double> &alpha,
const std::vector<double> &theta);
The Problem in your code has nothing to do with passing an Array to a function.
In your For-loop you try ]to set a Pointer (double*) to an Integer (1) which is the cause of you compiling error.
You have to Address the position of your Array with [] to set the value.
for(int i=0; i<3; ++i){
alpha[i] = 1.0;
theta[i] = 1.0;
}
This is identical with normal Pointers. To set the Value of the Pointer you have to dereference the Adress.
int* x = new int();
*x = 5;

returning array from function to main in c++

I have a bitset<112> called datain which is populated in a function seperate to the main one. I wish to split the bitset into an array of 14 bytes of uint8_t and return this array to the main function. I have written a for loop to do this. I have read about pointers to return an array and this is my best shot.
uint8_t* getDataArray()
{
bitset<112> datain;
// code to populate datin here
i = 111;
uint8_t *byteArray = new uint8_t[14];
bitset<8> tempbitset;
for (int j = 0; j<14; j++)
{
for (int k = 7; k >= 0; k--)
{
tempbitset[k] = datain[i];
--i;
}
*byteArray[j] = tempbitset.to_ulong();
}
return byteArray;
}
int main()
{
uint8_t* datain = getDataArray();
}
However this gives a compile error
error: invalid type argument of unary '*' (have 'uint8_t {aka unsigned char}')|
On the line
*byteArray[j] = tempbitset.to_ulong();
But from what I understand about pointers, byteArray[j] is the address for the data, and *byteArray[j] is the data so this should work???
thanks.
edited to take out another error my compiler pointed out once I had solved this error.
Because you have a pointer, you don't need to dereference and use operator[] on the array. The pointer points to the first element in the array. If you want another element, you can just use the subscript operator, without worrying about dereference.
Just do this:
byteArray[j] = tempbitset.to_ulong(); //write to position j in the array.

C++ two dimensional arrays with pointers

I have a problem with two dimensional arrays :( I feel very stupid and Visual C does not help me :( and I also think that my mistake is very stupid but still I can't find it :( I have this code:
double matrix[100][100]; //which is full with a matrix 3x4
double nVector[10000]; // for negative doubles
//I wanted to see if there are negative doubles in each row and column
//and I want this to happen with function
And this is my function:
double* negativeVector(double*nVector, double*fromVector, int m, int n){
int position = 0;
double *myNegArray = nVector;
double *myMatrix = fromVector;
for(int i = 0; i < m*n; i++)
if(*(*(myMatrix+i)) < 0){
*(myNegArray+position) = *(*(myMatrix+i));
position++;
}
return myNegArray;
}
//for double*nVector I'm passing nVector
//for double*fromVector I'm passing *matrix
Visual C tells me that I have an error C2100: illegal indirection here: *(*(myMatrix+i)) I hope someone can help me (happy)
Thanks in advance!
*(*(myMatrix+i)) is wrong. This is a common mistake.
2D matrix does not create an array of pointers which you can access this way. It is a different structure. Even though an array is a pointer, 2D array is not a pointer to pointer, and it cannot be dereferrenced twice. Nor you have any other way to access element at coordinates (x,y) without knowing the layout in memory, because pointers to every line are nowhere to be found. For instance, char **argv parameter of main() is not a 2D array. This is an array of pointers to arrays, which is something else.
There're two ways to fix it.
One is replace
double *myMatrix = fromVector;
by
double *myMatrix[100] = (appropriate cast)fromVector;
and index it as myMatrix[i/n][i%n]
But then remember that 100 is a constant expression, and it cannot be passed as a parameter. Alternatively, you can implement the indexing operation yourself:
Pass additional parameter: matrix line size (100)
Instead of *(*(myMatrix+i)), write:
int row = i/n;
int col = i%n;
*(myMatrix+row*line_size+col) is your element.
first you might wanna start a small struct like
struct tmp {
bool negative;
double value;
};
and make your own way up to the
tmp *myvars [100][100];
.
instead try using that struct and try the std::vectors instead of arrays if that's possible then try using pointers on decalring the variable "1 time only" when declaring the variable as i said above
then pass arguments
( tmp *mystructpointer )
mystructpointer->.......
access your matrix directly ... peice of cake :D
If you are passing *matrix, you are actually passing a double[100] (an array of 100 doubles), that happens to be passed as a pointer to its first element. If you advance further than those 100 doubles using i added to that pointer, you advance into the next array of 100 doubles, since the 100 arrays of 100 doubles are stored next to each other.
Background: A multi-dimensional array is an array whose element type is itself an array. An array like double a[100][100]; can be declared equivalently as typedef double aT[100]; aT a[100];. If you use an array like a pointer, a temporary pointer is created to the array's first element (which might be an array). The * operator is such an operation, and doing *a creates a pointer of type double(*)[100] (which is a pointer to an array of 100 doubles), and dereferences it. So what you end up with *matrix is a double[100]. Passing it to the negativeVector function will create a pointer to its first element, which is of type double*.
Your pointer parameters point to the start of each of two arrays of 100 doubles each. So you should rewrite the function as
double* negativeVector(double*nVector, double*fromVector, int m, int n){
int position = 0;
double *myNegArray = nVector;
double *myMatrix = fromVector;
for(int i = 0; i < m*n; i++)
if(*(myMatrix + i) < 0){
*(myNegArray + position) = *(myMatrix + i);
position++;
}
return myNegArray;
}
Notice that since your i iterates beyond the first of the 100 arrays stored in the 2d array, you will formally not be correct with this. But as it happens those arrays must be allocated next to each other, it will work in practice (and in fact, is recommended as a good enough work around for passing multi-dimensional arrays around as pointers to their first scalar element).
I have no clue why you are copying the arrays twice (once in the parameters of the function and a second time by declaring some new arrays)... You should also think of using the STL... std::vector will make the your life way easier ;)
double* negativeVector(double*nVector, double*fromVector, int m, int n){
int position = 0;
double *myNegArray = nVector;
double *myMatrix = fromVector;
for(int i = 0; i < m*n; i++)
if(*((myMatrix+i)) < 0){
*(myNegArray+position) = *((myMatrix+i));
position++;
}
return myNegArray;
}
is that homework? some templates - just for fun ;-)
double matrix[100][100];
double nVector[10000];
template< const int m, const int n >
double* negativeVector( double* myNegArray, const double (&myMatrix)[m][n] )
{
int position = 0;
for( int i = 0; i < m; ++i )
{
for( int j = 0; j < n; ++j )
{
const double value = myMatrix[ i ][ j ];
if ( value < 0 )
{
myNegArray[ position ] = value;
++position;
}
}
}
return myNegArray;
}
int main()
{
//...initialize matrix here...
negativeVector( nVector, matrix );
}
Perhaps rewrite this using std::vector to increase readability? (#):
#include <vector>
std::vector< std::vector<double> > matrix; //which is full with a matrix 3x4
std::vector<double> row;
row.resize(100,0);
matrix.resize(100,row);
std::vector<double> nVector; // for negative doubles, no size, we'll "push_back"
//I wanted to see if there are negative doubles in each row and column
//and I want this to happen with function
This is the stl enabled version of the function:
//I'm returning void because nvector contains the result,
//so I don't feel the need to return anything. vectors contain their
//own size so n and m are also not needed. Alsom pass in references
void negativeVector(std::vector<double>& nVector,
std::vector< std::vector<double> >& fromVector){
nVector.clear();
int i,j;
for(i = 0; i < fromVector.size(); i++) {
for(j = 0; j < fromVector[i].size(); j++) {
if(fromVector[i][j] < 0){
nVector.push_back(fromVector[i][j]);
}
}
}
}
call with:
negativeVector(nVector, matrix);
Once the function completes, nVector contains all negative numbers in matrix.
Read more about std::vector here.
(#) for people like me who are too lazy/stupid to comprehend code containing pointers.
Take a look at C++ Faq site:
How do I allocate multidimensional arrays using new?
link
And read until point [16.20] summarize all the answers you are getting and at the end you get a very useful Matrix template class.
Have a good read.