Pushing a 2d array onto a C++ STL stack? - c++

int test[5][5];
stack<int**> mystack;
mystack.push(test);
I get the error:
no matching function for call to ‘std::stack > >::push(int [5][5])’
/usr/include/c++/4.4/bits/stl_stack.h:182: note: candidates are: void std::stack<_Tp, _Sequence>::push(const typename _Sequence::value_type&) [with _Tp = int**, _Sequence = std::deque >]
I've never really used stacks before so I would appreciate any help. If I declare test as a one-dimensional array and stack as int*, it works fine.
Edit: I'm trying to implement backtracing for a sudokusolver. I have the sudoku grid as a 9x9 array of set objects (objects that hold the solution or possible solutions). I have to push the current state of the puzzle onto the stack, and then from there try guess and check. If a guess creates a contradiction (ie violates the rules of a sudoku), then I would pop from the stack to recover the puzzle before the invalid guess.

An int ** is not the same as a 2D array. A pointer to int test[5][5] would be int (*)[5], so you need a stack<int (*)[5]>. There's a good explanation of this here: Arrays and pointers in C.

In your example, test is not of type int**.
If you want a two-dimensional array, I would recommend using std::vector. This would certainly save your confusion with arrays and pointers...
typedef std::vector<std::vector<int> > two_d_vector;
two_d_vector test;
stack<two_d_vector> mystack;
mystack.push(test);

Related

iterate over std::vector of std::vector [duplicate]

I'm trying to pass a variable of type vector<vector<double> > to a function F(double ** mat, int m, int n). The F function comes from another lib so I have no option of changing it. Can someone give me some hints on this? Thanks.
vector<vector<double>> and double** are quite different types. But it is possible to feed this function with the help of another vector that stores some double pointers:
#include <vector>
void your_function(double** mat, int m, int n) {}
int main() {
std::vector<std::vector<double>> thing = ...;
std::vector<double*> ptrs;
for (auto& vec : thing) {
// ^ very important to avoid `vec` being
// a temporary copy of a `thing` element.
ptrs.push_back(vec.data());
}
your_function(ptrs.data(), thing.size(), thing[0].size());
}
One of the reasons this works is because std::vector guarantees that all the elements are stored consecutivly in memory.
If possible, consider changing the signature of your function. Usually, matrices are layed out linearly in memory. This means, accessing a matrix element can be done with some base pointer p of type double* for the top left coefficient and some computed linear index based on row and columns like p[row*row_step+col*col_step] where row_step and col_step are layout-dependent offsets. The standard library doesn't really offer any help with these sorts of data structures. But you could try using Boost's multi_array or GSL's multi_span to help with this.
The way I see it, you need to convert your vector<vector<double> > to the correct data type, copying all the values into a nested array in the process
A vector is organised in a completely different way than an array, so even if you could force the data types to match, it still wouldn't work.
Unfortunately, my C++ experience lies a couple of years back, so I can't give you a concrete example here.
Vector< Vector< double> > is not nearly the same as a double pointer to m. From the looks of it, m is assumed to be a 2-dimensional array while the vector is could be stored jagged and is not necessarily adjacent in memory. If you want to pass it in, you need to copy the vector values into a temp 2dim double array as pass that value in instead.

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.

2D array of structures with new keyword in C++!

I have a structure defined in a file called 'xxx.h':
struct struct_name
{
declarations;
};
I included this header - 'xxx.h' - in another c++ file, yyy.cpp
And then I try to create a 2D array of the above structure using new keyword as follows (I learnt how to create a 2D array of structures from this link: Declaring a 2D array of type struct in c++).
struct struct_name * some_name;
some_name = new struct struct_name[x][y];
When I compile, I get the following error: error: ‘y’ cannot appear in a constant-expression. This error particularly points to the second dimension of the array.
Also When I tried to initialize this 2D array of structures with some value like:
some_name[i][j].var_name = value;
I get the following error:
error: no match for ‘operator[]’ in ‘*(some_name + ((sizetype)(((unsigned int)i) * 12u)))[j]’
Please advise me how to fix this.
Thanks.
In the interest of getting you up and running as quickly as possible, I'm going to belay the usual memory layout diatribe and simply tell you one way to get your situation resolved.
The reason you're error is happening is because C++ requires knowledge of types when declaring an array, allocating an array, etc. When you do this:
some_name = new struct_name[x][y];
what you're telling the compiler is "I want to allocate x objects of type struct_name[y]". But struct_name[y] isn't a type known at compile-time. The size is unknown, but must be known (thus the error about a constexpr expectations. This would work:
struct_name (*some_name)[WIDTH] = new struct_name[x][WIDTH];
would work if WIDTH is a compile-time known-constant. But for you, that isn't constant so another solution is required.
Altnerative Approach
An alternative quick-fix approach is presented below
#include <vector>
int main()
{
int rows, cols;
// get row and column count.
typedef std::vector<struct_name> MatrixRow;
typedef std::vector<MatrixRow> Matrix;
Matrix some_name(rows, MatrixRow(cols));
// use some_name[i][j] however you need
return 0;
}
There are other ways to do this, but this is likely the fastest way to get you running. Further, it promotes proper RAII concepts. If you need a more specialized purpose of a 2D matrix you may have to develop your own class, as the C++ standard library has no direct 2D dynamic array concept natively, thus why we invent it using a vector of vector-types.
Try the declaration within yyy.cpp as:
struct struct_name **some_name;
The reason for this is that some_name[i] needs to be of type struct_name * in order to access another level of variables.
Do you really need a c++ arrays?
Why not use std::vector<std::vector<struct_name>> ?
If you don't need dynamic allocation then you could use:
std::array<std::array<struct_name, 2>, 3> where 2 and 3 are the sizes of your 2D array.

access violation in 3-dimensional array c++(using malloc)

I am trying to make a 3-d integer array where I know the number of columns is 2.
I am initializing the array sequentially using malloc. Please suggest what could be wrong?
int **output_vertex[2];
for(int j=0;j<4;j++)
output_vertex[j]= (int **)malloc(sizeof(int **));
output_vertex[1][0]==(int*)malloc(2*sizeof(int));
output_vertex[1][0][0] =11;
//also tried *output_vertex[1][0] =11;
I'm having a bit of trouble understanding what your error is (or which one you'd be referring to). Firstly I don't know why you're statically creating an array and then using malloc. Secondly, I don't understand why you're iterating through your for loop four times (0, 1, 2, 3). Shouldn't your allocation be something like this:
int **output_vertex;
output_vertex = (int **)malloc(2*(sizeof(int **)));
The array declaration you have is not what you intended. You have a two-element array of pointers to pointers to int. This page is a good guide to reading those declarations.
Personally, I prefer to use typedefs and build a complex type like this from the ground up:
typedef int[2] element_type; // this is the 2-element array of ints
typedef element_type* inner_type; // this is the array of unknown size
typedef inner_type[5] outer_type; // this is the actual type we want to use
outer_type output_vertex; // we now have an array of 5 inner_type variables on the stack
// The output_vertex is *uninitialized* so we have to initialize each of its elements
for (int i=0; i < 5; ++i) {
output_vertex[i] = new inner_type[SOME_SIZE];
}
// do stuff with output_vertex now that it's initialized
// then, to prevent memory leaks, delete the memory you allocated
for (int i=0; i < 5; ++i) {
delete[] output_vertex[i];
}
There are probably ways to simplify, but that should be a start.
If you want the inner_type to be appendable, I would strongly recommend using std::vector instead of raw arrays. There is far much bookkeeping to be done with raw arrays, so I won't give an example of that; however, here's more-or-less what you would do with std::vector:
typedef std::pair<int,int> element_type; // this is the 2-element array of ints as a pair
typedef std::vector<element_type> inner_type; // dynamic vector this time
inner_type output_vertex[5]; // we now have an array of 5 inner_type variables on the stack
// do stuff with output_vertex
std::vector is just as fast as a dynamically-allocated array, but you don't have to do any of the bookkeeping yourself. You also have the benefit of not needing to manage as many heap-allocated objects.
Note that raw arrays aren't compatible with containers (e.g. std::vector), so I use std::pair here instead.
If you're able to use C++11 (or boost) and you need a fixed-size array of greater than two items that can fit into a standard container, use std::array.

assign elements in vector declared with new. C++

I am trying to use a large 2D vector which I want to allocate with new (because it is large).
if I say:
vector< vector<int> > bob;
bob = vector< vector<int> >(16, vector<int>(1<<12,0));
bob[5][5] = 777;
it works. But if I say:
std::vector< std::vector<int> > *mary;
mary = new vector< vector<int> >(16, vector<int>(1<<12, 0));
mary[5][5] = 777;
it doesn't work and I get the error:
Error 1 error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion) c:\Users\jsparger\Documents\My Dropbox\ARI\VME_0.01\VME_0.01\V965.cpp 11 VME_0.01
Obviously I am new to C++. Could someone explain what syntax I need to use to perform this operation. mary is a pointer, so I can see why this wouldn't work, but *mary[5][5] = whatever is not allowed either because of "new", right?
Thanks for the help. This vector is what I will be using for now because it seems easy enough for my small c++ brain to understand, but feel free to let me know if a large vector like this is a bad idea, etc.
Thanks a bunch.
Edit:
I am mistaken about the "not allowed because of new". I don't know where I misread that, because it obviously works, and wouldn't make too much sense for it not to. Thanks.
If mary is a pointer then you have to dereference it before applying the subscript operator:
(*mary)[5][5] = 777;
The parentheses are required because the subscript has higher precedence than the dereference.
Vectors store their elements on the heap, anyway. There's no point in allocating the vector object itself on the heap, since it is very small (typically 12 bytes on a 32-bit machine).
In plain C, arrays and pointers are similar (not the same!), which leads to your confusion. In plain C, if you have the following declarations:
int array1[100];
int *array2 = (int *)malloc(100*sizeof(int));
you can use array1 and array2 in exactly the same way.
However, if you write this in C:
int (*array3)[100];
This is something completely different. Array3 is now a pointer to an array, not a pointer to the elements of the array anymore, and if you want to access an element, you have to write this:
(*array3)[5] = 123;
In C++, you are actually doing something similar, the second 'mary' is a pointer to the vector, not a pointer to the elements in the vector. Therefore, you have to write this:
(*mary)[5][5] = 777;