I am trying to solve a dynamic programming problem and I need to take the user input in the form of a 2-d array and use the values from the 2-d array inside the function.
The values of the 2-d array will not be changed when used inside the function.
In the function int dp i am getting the
error:
declaration of 'a' as multidimensional array must have bounds for all dimensions except the first
int max(int a,int b,int c)
{
if(a>=b && a>=c)return a;
if(b>=c && b>=a)return b;
else return c;
}
int max2(int a,int b)
{
if(a>b)return a;
else return b;
}
int dp(int i,int j,int a[][],int p,int q)
{
if((i-1)>=0 && (j-1)>=0 &&(i+1)<p &&(j+1)<q )
return max(a[i][j]+dp(i-1,j+1,a,p,q),a[i][j]+dp(i+1,j+1,p,q),
a[i][j]+dp(i,j+1,p,q));
if(i==0 && j!=0 && (j+1)<q)
return max2(a[i][j]+dp(i+1,j+1,p,q),a[i][j]+dp(i,j+1,p,q));
}
int main()
{
int p,q,r,s,T,a,b,i,j,k;
scanf("%d",&T);
for(a=0;a<T;a++)
{
scanf("%d %d",p,q);
int z[p][q];
int max=0;
for(i=0;i<q;i++)
{
for(j=0;j<p-1;j++)
scanf("%d ",&z[j][i]);
scanf("%d",&z[j+1][i]);
}
for(i=0;i<p;i++)
{
if(dp(i,0,z,p,q)>max)
max=dp(i,0,z,p,q);
}
}
}
It's all in the error message:
declaration of 'a' as multidimensional array must have bounds for all dimensions except the first
Your function signature does not have bounds for a's 2nd dimension:
int dp(int i,int j,int a[][],int p,int q)
// ^^^^^
You need to fill it in with a[][N] where N is whatever the correct bound is. The issue is that you are using VLAs here:
scanf("%d %d",p,q);
int z[p][q];
That is non-standard C++, and basically means you cannot write the signature of dp, since the second bound has to be known as a compile-time constant. You could either make it a single-dimensional array:
int* z = new int[p*q];
int dp(int i, int j, int* a, int p, int q)
// ^^^^^^
or dynamically allocate it in 2 dimensions and just pass it in that way:
int** z = new int*[p];
for (int i = 0; i < p; ++i) {
z[i] = new int[q];
}
int dp(int i, int j, int** a, int p, int q)
// ^^^^^^^
The function dp needs some information to perform meaningful index calculations, either done by the compiler or in the actual inplementation. Either a dimension must be specified in the type or the argument a could be of type int** while its dimensions are provided as separate arguments to dp. As this is C++, a type of std::vector< std::vector< int > > might be more suitable for the task.
You get that error because you cannot leave both the index(row,column) empty in int a[][] in your function declaration. You must have both specified or atleast the value of column index.
Use dynamic declaration
int **z = new int*[p];
for (int i = 0; i < p; i++)
z[i] = new int[q];
Change the parameter int a[][] to int **a
You can't dynamically declare an array on the stack as the size has to be known at compile time. The only way to do this would be by allocating memory for the array on the heap using the new keyword, then you could declare the size at run time.
Far easier, however, would be just to use a container class, or in your case, a container of containers like a vector of vector of ints;
#include <vector>
vector< vector<int> > arrArray(rows, vector<int>(columns));
The syntax might look a bit strange, but breaking it down;
vector<int> - a vector of type int
vector< vector<int> > - a vector of vectors of type int
arrArray(rows, vector<int>(columns)); - here in the first parameter, we are saying; create rows number of vector<int>'s in our array, and the second parameter initalises the array to some value. If it were just a 2D array of int, we might initalise it to 0, or omit the second parameter and rely on the default value of int. But, because our multidimensional vector also contains vectors, we set each row of our main vector to store a vector of int's which holds columns amount of integers.
Now you can access the array like you would any other;
arrArray[2][0] = 5;
You also get all the added benefits that container classes contain, including iterators and a lot of useful class methods for manipulating and checking your array. Once you understand the syntax of creating container classes, you'll find them much easier to work with than arrays. You also don't have to worry about having to manage your own memory, and have the ability to do bounds checking before accessing vector elements.
Related
how can I cast void pointer to a 2d array (array of pointers to arrays of ints), when I dont know array size at compile time? Is it somehow possible? (I am doing this because, I pass an 2d array of unknow size to a func. So I cast 2d array to a void pointer and then in that func I want it to recast back.)
int i = 5;
int tab1[i][i];
//cast to void pointer
void *p = (void *)tab1;
//and recast back
int (*tab2)[5] = (int (*)[5])p; //this is working
int (*tab3)[i] = (int (*)[i])p; // but this is not
First I suggest to don't use runtime size for array in C/C++, except you using STL vector as an array. so instead of:
int i = 5;
you must use:
const int i = 5;
except you use Vector that is safe and better than intrinsic arrays.
how can I cast void pointer to a 2d array (array of pointers to arrays of ints), when I dont know array size at compile time? Is it somehow possible?
If we talk about C intrinsic array, It is not possible!
why it is not possible?
because C/C++ compiler not aware of your the array size, borders,.... so if you cast your 2d array to 1d array, it is possible. it is the reason that tab2 array can access to first 5th element of your array. really C/C++ compiler cannot distinguish the different of
int a[3][3]
with
int a[3*3]
so You must be aware of at least one dimension of your array:
int main() {
const int i = 3,j = 4;
int tab1[i][j] = {1,2,3,4,5,6,7,8,9,10,11};
//cast to void pointer
void *p = (void *)tab1;
auto a = (int (*)[i][12/i])p;
return 0;
}
In the above example, I aware about i and total count(12) and I calculate the second dimension.
I use auto keyword that very easily inferred the data type.
int i = 5; int tab1[i][i]; is a VLA. It's not standard C++ and should be avoided.
An array-of-pointers-to-arrays (and vector-of-vectors) won't be as efficient as a true 2D array since it's no longer contiguous (int tab1[5][5] is a true 2D array and is stored contiguously in memory, but the dimensions must be known at compile-time).
You can easily create a custom 2D container class that would store the data in a contiguous 1D vector and apply some simple math (x + y*width) to access the elements.
Example:
class Matrix {
std::vector<int> data;
public:
const int width;
const int height;
Matrix(int width, int height) : width(width), height(height), data(width*height) {}
int operator()(int x, int y) const {
return data[y * width + x];
}
int& operator()(int x, int y) {
return data[y * width + x];
}
};
void print(Matrix const& mat) {
for (int y = 0; y < mat.height; y++) {
for (int x = 0; x < mat.width; x++)
std::cout << mat(x, y) << " ";
std::cout << std::endl;
}
}
int main() {
Matrix mat(5, 5);
mat(1, 1) = 1;
mat(2, 2) = 2;
mat(3, 3) = 3;
print(mat);
}
For convenience this overloads the () operator. It's still possible with the [] operator but that will require a proxy class to access the inner dimension(s) and also putting y before x since the dimensions are actually reversed.
int tab1[i][i]; is a non-standard compiler extension for variable length arrays. It is better to avoid this because it is not portable and hard to deal with as you are seeing. You would be better with:
std::vector<std::vector<int>> tab1(i, std::vector<int>(i));
Then your function can simply take this vector:
void foo(const std::vector<std::vector<int>>& array) { ....
how can I cast void pointer to a 2d array (array of pointers to arrays of ints), when I dont know array size at compile time?
You can't. You can only cast to a type that is known at compile time.
What you can do is convert to a pointer to first element of the first row: int* p = static_cast<int*>(tab1);. You can then treat the array as one dimensional1. Converting two dimensional indices to one dimensional requires some trivial math: x, y -> x + y * i.
1 As long as you don't mind the technicality that pointer arithmetic across the sub array boundary might technically not be allowed by the standard. But that rule is silly. If you're concerned about this, then you should create a one dimensional array in the first place.
The problem you are having here is that the size of an array must be defined at compile time.
In your case, you have multiple options:
make i a constexpr like constexpr int i = 5;
use a int ** instead:
int i = 5;
int tab1[i][i];
//cast to void pointer
void *p = (void *)tab1;
// cast to int **
auto tab1_p = (int **)p;
// use it like it was an array
tab1_p[1][3] = 5;
When I try to run this simple code, it returns a Variable-sized object may not be initialized error. I have no idea why and how to resolve this problem.
int main()
{
int n=0;
n=1;
int a[n]={}, b[n]={};
return 0;
}
The array lenght must be known at compile time.
Either
int a[1];
or
constexpr int n = 1;
int a[n];
Otherwise you need a dynamic array like the std container std::vector.
You can initialize your array properly with the std::fill_n like:
std::fill_n(a, n, 0);
std::fill_n(b, n, 0);
or use std::vector like:
std::vector<int> a(n);
It will initialize all the elements to 0 by default.
Or, you can have something like:
constexpr size_t n = 10;
int a[n]{};
This will also initialize all the elements to 0.
Try this:
const int n=1;
int main()
{
int a[n]={}, b[n]={};
return 0;
}
The above code will let you create an array with length n.
Note: n can't be changed.
So I am currently working on a program in c++, and I want to make the following decleration:
methodOne()
{
vector<int> one;
vector<int> two;
... assigning to one and two...
int a = one.size();
int b = two.size();
methodTwo(a, b);
}
methodTwo(int a, int b)
{
int array[a][b];
}
When I attempt this, I get an error: a and b must be constant
I have tried to assign a and b to const int a, const int b. However, that was no help. I was wondering if anyone knows how I can fix this kind of error. Thanks in advance for any help you are able to give!
An array's size must be known before the program runs. Its size is part its complete type, just like the element type itself.
You need something with a dynamic size instead. Use a std::vector<int> of size a * b:
methodTwo(int a, int b)
{
std::vector<int> array(a * b);
}
You could also use a std::vector<std::vector<int>> instead, but why take all the trouble? After all, you can access the one-dimensional vector's elements as if it was two-dimensional data structure by calculating the offsets accordingly:
methodTwo(int a, int b)
{
std::vector<int> array(a * b);
// ...
int x = 5;
int y = 6;
auto const element = array[y * a + x];
}
I see you already using vector so you can replace your array with
typedef std::vector< std::vector<int> > matrix;
matrix name(a, std::vector<int>(b));
I have to call a function which passes 2d array as argument. Function call:
int n;
char ch;
cin>>n;
bool b[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>ch;
if(ch=='X'){b[i][j]=1;} //reads input from a file
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cout<<evaluate(n,b, i, j); //shows error no matching function for call to evaluate
}
cout<<endl;
}
However,it displays an error no matching function to the call
Here's my function evaluate's declaration:
int evaluate(int n,bool** b,int x,int y){
//body
}
I have tried variations in function declaration as:evaluate(int n,bool b[n][n],int x,int y);
but it gives the same error. Also on removing the 2d array argument,the function works.
Please suggest what my mistake is.
Array names converted to pointer to first element of array when passed to a function. A 2D array is a 1D array having all its elements of type 1D array, i.e it is an array of arrays.
When 2D array name passed to a function then it decays to pointer to first element of the array. As explained above, the element itself is a 1D array, therefore the type of array name becomes pointer to array.
pointer to array and pointer to pointer both are of different types (incompatible with each other). To pass a pointer to array type, you need to declare your function as
int evaluate(int n, bool (*b)[n], int x, int y);
or simply
int evaluate(int n, bool b[][n], int x, int y);
What you need to understand is that a 2D array (a variable declared as int foo[m][n];) is something very different from a double pointer (a variable of type int **foo;). Even though you may use foo[i][j] in both cases, what happens is radically different:
In the case of a 2D array, foo[i][j] is effectively evaluated as foo[i*m + j], all the lines of the 2D array are contiguous in memory, and there is no index structure.
In the case of a double pointer, foo[i][j] first loads a pointer from memory at foo[i], then it loads an int from behind that loaded pointer. That is, foo must point to an array of pointers, that indices into the different line arrays. The line arrays may be independent of each other, they are connected via the index array.
Consequently, you cannot just pass a 2D array as an int** to a function since there is no index array in the 2D array.
However, you can pass a pointer to an array (pseudocode, I omitted declaring some variables):
const int width = ...;
void foo(int (*twoDArray)[width], int x, int y) {
//do something with twoDArray[x][y]
}
int main() {
int myArray[height][width];
foo(myArray, x, y);
}
Unfortunately, width has to be a compile time constant in C++. C can handle dynamic array size, C++ cannot. This severely limits the usability of this approach.
Do you defined your function (callee) before main (caller) function?
you should do like this:
int evaluate(int n,bool** b,int x,int y);
int main(){
//some code
evaluate(n, b, i, j);
//some code
}
int evaluate(int n,bool** b,int x,int y){
//body
}
or this way:
int evaluate(int n,bool** b,int x,int y){
//body
}
int main(){
//some code
evaluate(n, b, i, j);
//some code
}
How should I return an array from a function? My code is
float ClassArray::arr_sub(float a[100][100], float b[100][100]) {
int i,j;
for(i = 1; i < 10; i++) {
for(j = 1; j < 10; j++){
f[i][j]=b[i][j]-a[i][j];
}
}
return f;
}
and the f returned from this function should be assigned to another array g declared in some other class.
float g[100][100];
g= cm.arr_sub(T,W);
but while building the classes, it says incompatible type assignment of float to float[100][100].
My answer here to another question on arrays explains why you don't want to use arrays.
As I say in that answer you can't assign an array like you're trying:
float g[100];
g = foo(); // illegal, assigning to arrays is not allowed
Another of the weird restrictions on arrays is that you're not allowed to return them from functions:
float foo()[100]; // illegal, returning an array from a function is not allowed
Also note that when you declare a function like float arr_sub(float a[100][100]) you might think you're passing an array by value, but in fact that invokes another of the weird exceptions made for arrays. In C and C++, whenever you declare a formal parameter of a function to be an array, the type is adjusted from 'array' to 'pointer to the array's element type'.
Since arrays don't behave like they ought, you should instead use std::array or std::vector:
std::array<float,100> foo(); // works
std::array<float,100> g;
g = foo(); // works
To do multi-dimentional arrays you can use:
std::array<std::array<float,100>,100> g;
Though that's a bit cumbersome so you can typedef it:
typedef std::array<std::array<float,100>,100> Matrix;
Matrix ClassArray::arr_sub(Matrix a, Matrix b) {
...
}
Matrix g;
g = cm.arr_sub(T,W);
And if you have a compiler that supports C++11 you can even do a template type alias:
template<typename T,int Rows,int Columns>
using Matrix2d = std::array<std::array<T,Columns>,Rows>;
Matrix2d<float,100,100> g;
Note on performance
There is one reason you might not want to return an std::array by value. If the array is large then there may be a signficant performance cost in copying the data from the return value into the variable you assign it to. If that ever proves to be a problem for you, then the solution with std::array is the same as it would be for other large types; use an 'out' parameter instead of returning by value.
void arr_sub(Matrix a, Matrix b, Matrix &result);
Matrix g;
arr_sub(T,W,g);
This doesn't apply to std::vector because std::vector can take advantage of move semantics to avoid having to copy all its elements.
If you insist on using "plain C" 2D arrays, the best thing is to pass a pointer to the result along with the two input parameters, rather than passing the arrays by value the way you did.
However, the best thing to do in C++ is to use vector<vector<float> > instead, and pass it by reference.
void ClassArray::arr_sub(
const vector<vector<float> > &a
, const vector<vector<float> > &b
, vector<vector<float> > &res)
{
for(int i=0 ; i != a.size() ; i++)
for(int j=0 ; j != b.size() ; j++)
res[i][j] = b[i][j] - a[i][j];
}
void main() {
vector<vector<float> > a(100, vector<float>(100, 12.345));
vector<vector<float> > b(100, vector<float>(100, 98.765));
vector<vector<float> > res(100, vector<float>(100, 0));
arr_sub(a, b, res);
}
The best way to do this is to wrap everything into a class. From the look of things, its a Matrix.
There are probably a hundred Matrix classes out there already, so it is really pointless to write another one.
But, if this is a learning exercise it might be worthwhile.
To answer your asked question, make a third argument to your function: float result[100][100]. Inside your function, write the results into the result array.
This works because in C and C++, arrays are always passed by reference and never by value. This is because C++ passes only the pointer to the beginning of the array.
if you really wish to return an array and some how manage to use it in the main(), the most efficient way would be to declare the returning array as dynamic. that way you will avoid losing the pointer to this new array as it will be allocated in heap and not in stack.