I have created a 2D vector and inserted element accordingly for example
vector < vector<int> > tube;
for(int i=0;i<2;i++)
{
tube.push_back(vector<int> ());
for(int j=0;j<5;j++)
{
tube[i].push_back(j);
}
}
Now I want to pass only row of vector to a function not the whole vector
void print(vector < vector<int> > tube){
}
print (tube)//not like this
print (tube[0]) I want to pass first row of every element
print (tube[1]) or second row of every element.
Please help me how to do it.
You should declare something like this:
void print(const vector<int> &row){
// print here contents of row, which is received as const reference
}
And then you call it like this:
print(tube[i]);
This way your print() function receives a reference to the row you want to print. The row is not copied, which helps save time and memory. The const keyword is guaranteeing that the print() function is not going to alter the contents of the vector; this makes it possible to call print() with const vectors as arguments, if you needed to.
You can do it by changing the signature of print to void print( const vector< int > &row ). However, conceptually you seem to be dealing with a matrix.
Related
I have a vector variable named intVec, and I have a function named pushBack, that accepts a vector of type integer just like intVec, but when I actually pass that vector into the function in order to push_back the x parameter, nothing seems to happen.
Output expected from intVec.size() is 1
Output given from intVec.size() is 0
I'm genuinely confused as to what I'm doing incorrectly here.
Perhaps I'm missing something extremely obvious.
#include <vector>
std::vector<int> intVec;
void pushBack(int x, std::vector<int> vec) {
vec.push_back(x);
}
int main() {
pushBack(10, intVec);
std::cout << intVec.size();
}
That is because you pass the vector by value instead of by reference (or pointer).
This means, that when you call the function, the vector you call 'push_back' on is actually an independent copy of the original vector, which get deallocated upon leaving the function.
Try this header instead:
void pushBack(int x, std::vector<int> &vec) {
vec.push_back(x);
}
The & tells the compiler to pass by reference, meaning that whatever you do to vec, you also do to the vector you originally passed.
Write pushBack as below:
void pushBack(int x, std::vector<int>& vec) {
vec.push_back(x);
}
The only difference is that here vec is being passed by reference. In your code it is being passed by value.
I want to insert values into a vector of set<int>, which is defined using typedef as given below:
typedef std::set<int> blockSet_t;
std::vector<blockSet_t>* myvector
I want to have values such that myvector[0] has a set of ints, myvector[1] has a different set of ints and so on.
Currently, I am passing this vector to a function which is parsing a file that has the set of integers.
Like:
main()
{
std::vector<blockSet_t> myvector;
filereader(myvector);
}
I read the set from the file and store it in a different blockSet_t myset;
I am using the following loop to store this set to a specific location in the vector:
filereader(&myvector)
{
for(int i=0;i<size;i++)
{
myvector.push_back(myset); // It does not give error but I don't know myset is stored in which location
//what I want is to have someting like this
myvector[i].push_back(myset); //so I can store different sets at different locations
}
}
I also could not figure out, how to display the values from within thevector.
Since it is a vector of sets, I want to display each set (on a different vector index).
Any help in this regard is much appreciated.
Thanks.
First of all, push_back function is called push_back because it pushes an object back.
It means that, if your vector is empty and you call push_back your pushed object will have 0 location.
If your vector has n objects inside it, this means after push_back your pushed object will have n-th index.
myvector.push_back(myset);
std::cout<<"index of myset is "<<myvector.size()-1<<std::endl;
Secondly, if you want to print values, you have to create your own operator<< overloading function for std::ostream class. This is a common way of printing values in C++.
Assume you want to print set in curly {} brakets and vector in square [] ones:
#include <ostream>
inline std::ostream& operator<<(std::ostream &os,const blockSet_t &mySet)
{
os<<"{ ";
for(const auto &value:mySet)
{
os<<value<<' ';
}
os<<"};
return os;
}
inline std::ostream& operator<<(std::ostream &os,const std::vector<blockSet_t> &myvector)
{
os<<"[ ";
for(const auto &mySet:myvector)
{
os<<mySet<<' ';
}
os<<"];
return os;
}
Next, you have to cout your object like this:
#include <ostream>
main()
{
std::vector<blockSet_t> myvector;
filereader(myvector);
std::cout<<myvector<<std::endl;
}
I am trying to return an array Data Member from one smaller 2D Array Object, and trying to insert the array into a larger 2D array object. But when attempting this, I came into two problems.
First problem is that I want to return the name of the 2D array, but I do not know how to properly syntax to return 2D Array name.
This is what my 2D Array data member looks like
private:
int pieceArray[4][4];
// 2D Smaller Array
and I want to return this array into a function, but this one causes a compiler error:
int Piece::returnPiece()
{
return pieceArray; //not vaild
// return the 2D array name
}
I tired using this return type and it worked:
int Piece::returnPiece()
{
return pieceArray[4][4];
}
But I am unsure if this is what I want, as I want to return the array and all of it's content.
The other problem is the InsertArray() function, where I would put the returnPiece() function in the InsertArray()'s argument.
The problem with the InsertArray() is the argument, heres the code for it:
void Grid::InsertArray( int arr[4][4] ) //Compiler accepts, but does not work
{
for(int i = 0; i < x_ROWS ; ++i)
{
for (int j = 0; j < y_COLUMNS ; ++j)
{
squares[i][j] = arr[i][j];
}
}
}
The problem with this is that it does not accept my returnPiece(), and if i remove the "[4][4]", my compiler does not accept.
Mostly all these are syntax errors, but how do I solve these problems?
Returning the whole pieceArray in returnPiece()
The correct syntax for the argument in InsertArray()
The argument of InsertArray() accepting the returnPiece()
These 3 are the major problems that I need help with, and had the same problem when I attempt to use the pointer pointer method. Does anyone know how to solve these 3 problems?
When passing your array around, you have to decide whether or not you want to make a copy of the array, or if you just want to return a pointer to the array. For returning arrays, you can't (easily) return a copy - you can only return a pointer (or reference in C++). For example:
// Piece::returnPiece is a function taking no arguments and returning a pointer to a
// 4x4 array of integers
int (*Piece::returnPiece(void))[4][4]
{
// return pointer to the array
return &pieceArray;
}
To use it, call it like so:
int (*arrayPtr)[4][4] = myPiece->returnPiece();
int cell = (*arrayPtr)[i][j]; // cell now stores the contents of the (i,j)th element
Note the similarity between the type declaration and using it - the parentheses, dereferencing operator *, and brackets are in the same places.
Your declaration for Grid::InsertArray is correct - it takes one argument, which is a 4x4 array of integers. This is call-by-value: whenever you call it, you make a copy of your 4x4 array, so any modification you make are not reflected in the array passed in. If you instead wanted to use call-by-reference, you could pass a pointer to an array instead:
// InsertArray takes one argument which is a pointer to a 4x4 array of integers
void Grid::InsertArray(int (*arr)[4][4])
{
for(int i = 0; i < x_ROWS; i++)
{
for(int j = 0; j < y_COLUMNS ; j++)
squares[i][j] = (*arr)[i][j];
}
}
These type declarations with pointers to multidimensional arrays can get really confusing fast. I recommend making a typedef for it like so:
// Declare IntArray4x4Ptr to be a pointer to a 4x4 array of ints
typedef int (*IntArray4x4Ptr)[4][4];
Then you can declare your functions much more readable:
IntArray4x4Ptr Piece::returnPiece(void) { ... }
void Grid::InsertArray(IntArray4x4Ptr arr) { ... }
You can also use the cdecl program to help decipher complicated C/C++ types.
It seems like you need to read up more on pointers in C++ and on pass by reference vs. pass by value.
Your returnPiece method is defined as returning the value of a single cell. Given the index (e.g., [4][4]) you return a copy of the contents of that cell, so you won't be able to change it, or more correctly, changing it would change the copy.
I'm sure someone will give you the correct syntax, but I would really recommend learning this stuff since otherwise you may use the code that you do get incorrectly.
Here is how I would do it:
class Array {
public:
Array() {
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
(*this)(i, j) = 0;
}
}
}
int &operator()(int i, int j)
{
return pieceArray[i][j];
}
private:
int pieceArray[4][4];
};
You can then do something like:
Array x; // create 4x4 array
x(1, 2) = 3; // modify element
Trouble with Adam Rosenfield's arrayPtr in that Piece::pieceArray can change out from under you. (Copy-by-reference vs Copy-by-value.)
Copy-by-value is inefficient. But if you really want to do it, just cheat:
struct FOO { int piece [4][4]; };
FOO Piece::returnPiece()
{
FOO f;
memcpy( f.piece, pieceArray, sizeof(pieceArray) );
return f;
}
void Grid::InsertArray( const FOO & theFoo )
{
// use theFoo.piece[i][j]
}
Of course, a better, more Object-Oriented solution, would be to have returnPiece() create and return a Piece or Array object. (As Juan suggested...)
Suppose I have
vector<vector<int> > a;
which is indexed as
a[i][j] = stuff;
where i is "outer" and j is "inner"...
Then creating a reference to the "outer" vector is easy:
vector<int>& b = a[x];
Is there a nice way to create a reference to the inner?
vector<int>& b = a[<don't know>][x];
Thanks.
Unfortunately, no, there's no direct way of creating a reference like that because the compiler is treating this like
a.operator[] (/* ... don't know ... */).operator[] (x);
This only makes sense if the first call to operator [] actually hands back a vector.
However, what you can do is fake this behavior by introducing a new class that specifically handles the behavior. The idea is to have this class store the second index and provide an operator[] function that, given the first index, looks up the real value in the vector. Here's one example:
class IndexReverser { // Or, your favorite name
public:
IndexReverser(vector< vector<int> >& v, size_t index);
int& operator[] (size_t firstIndex);
private:
vector< vector<int> >& realVector;
const size_t secondIndex;
};
IndexReverser::IndexReverser(vector< vector<int> >&v,
size_t index) : realVector(v), secondIndex(index) {
// Handled in initialization list
}
int& IndexReverser::operator[] (size_t firstIndex) {
return realVector[firstIndex][secondIndex];
}
You could then write, for example, this:
IndexReverser ir(a, j);
ir[i] = 137;
You might need to provide a twin class to handle const vectors, and probably would want to parameterize the entire structure on the type of the elements being stored. I'm not sure if this is what you're looking for, but it least shows that in principle you can get the behavior you want.
This line:
vector<int>& b = a[x];
is not a reference to the outer vector but rather one of the inner vectors. Also note that there are possible many inner vectors.
Here's how to get a reference to the outer vector (although in general it would be pointless):
vector<vector<int> > &outer = a;
Getting a reference to one of the inner vectors looks something like this:
vector<int> &inner = a[x];
I am trying to return an array Data Member from one smaller 2D Array Object, and trying to insert the array into a larger 2D array object. But when attempting this, I came into two problems.
First problem is that I want to return the name of the 2D array, but I do not know how to properly syntax to return 2D Array name.
This is what my 2D Array data member looks like
private:
int pieceArray[4][4];
// 2D Smaller Array
and I want to return this array into a function, but this one causes a compiler error:
int Piece::returnPiece()
{
return pieceArray; //not vaild
// return the 2D array name
}
I tired using this return type and it worked:
int Piece::returnPiece()
{
return pieceArray[4][4];
}
But I am unsure if this is what I want, as I want to return the array and all of it's content.
The other problem is the InsertArray() function, where I would put the returnPiece() function in the InsertArray()'s argument.
The problem with the InsertArray() is the argument, heres the code for it:
void Grid::InsertArray( int arr[4][4] ) //Compiler accepts, but does not work
{
for(int i = 0; i < x_ROWS ; ++i)
{
for (int j = 0; j < y_COLUMNS ; ++j)
{
squares[i][j] = arr[i][j];
}
}
}
The problem with this is that it does not accept my returnPiece(), and if i remove the "[4][4]", my compiler does not accept.
Mostly all these are syntax errors, but how do I solve these problems?
Returning the whole pieceArray in returnPiece()
The correct syntax for the argument in InsertArray()
The argument of InsertArray() accepting the returnPiece()
These 3 are the major problems that I need help with, and had the same problem when I attempt to use the pointer pointer method. Does anyone know how to solve these 3 problems?
When passing your array around, you have to decide whether or not you want to make a copy of the array, or if you just want to return a pointer to the array. For returning arrays, you can't (easily) return a copy - you can only return a pointer (or reference in C++). For example:
// Piece::returnPiece is a function taking no arguments and returning a pointer to a
// 4x4 array of integers
int (*Piece::returnPiece(void))[4][4]
{
// return pointer to the array
return &pieceArray;
}
To use it, call it like so:
int (*arrayPtr)[4][4] = myPiece->returnPiece();
int cell = (*arrayPtr)[i][j]; // cell now stores the contents of the (i,j)th element
Note the similarity between the type declaration and using it - the parentheses, dereferencing operator *, and brackets are in the same places.
Your declaration for Grid::InsertArray is correct - it takes one argument, which is a 4x4 array of integers. This is call-by-value: whenever you call it, you make a copy of your 4x4 array, so any modification you make are not reflected in the array passed in. If you instead wanted to use call-by-reference, you could pass a pointer to an array instead:
// InsertArray takes one argument which is a pointer to a 4x4 array of integers
void Grid::InsertArray(int (*arr)[4][4])
{
for(int i = 0; i < x_ROWS; i++)
{
for(int j = 0; j < y_COLUMNS ; j++)
squares[i][j] = (*arr)[i][j];
}
}
These type declarations with pointers to multidimensional arrays can get really confusing fast. I recommend making a typedef for it like so:
// Declare IntArray4x4Ptr to be a pointer to a 4x4 array of ints
typedef int (*IntArray4x4Ptr)[4][4];
Then you can declare your functions much more readable:
IntArray4x4Ptr Piece::returnPiece(void) { ... }
void Grid::InsertArray(IntArray4x4Ptr arr) { ... }
You can also use the cdecl program to help decipher complicated C/C++ types.
It seems like you need to read up more on pointers in C++ and on pass by reference vs. pass by value.
Your returnPiece method is defined as returning the value of a single cell. Given the index (e.g., [4][4]) you return a copy of the contents of that cell, so you won't be able to change it, or more correctly, changing it would change the copy.
I'm sure someone will give you the correct syntax, but I would really recommend learning this stuff since otherwise you may use the code that you do get incorrectly.
Here is how I would do it:
class Array {
public:
Array() {
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
(*this)(i, j) = 0;
}
}
}
int &operator()(int i, int j)
{
return pieceArray[i][j];
}
private:
int pieceArray[4][4];
};
You can then do something like:
Array x; // create 4x4 array
x(1, 2) = 3; // modify element
Trouble with Adam Rosenfield's arrayPtr in that Piece::pieceArray can change out from under you. (Copy-by-reference vs Copy-by-value.)
Copy-by-value is inefficient. But if you really want to do it, just cheat:
struct FOO { int piece [4][4]; };
FOO Piece::returnPiece()
{
FOO f;
memcpy( f.piece, pieceArray, sizeof(pieceArray) );
return f;
}
void Grid::InsertArray( const FOO & theFoo )
{
// use theFoo.piece[i][j]
}
Of course, a better, more Object-Oriented solution, would be to have returnPiece() create and return a Piece or Array object. (As Juan suggested...)