Insert values in a vector of int sets in C++ - c++

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;
}

Related

Manage memory on vector assignment

(This question can be extended to others containers)
I can use a vector to storage a lot of data then it is important to know how the c++ manage the assignment to this container specially if I don't have a lot of memory.
a) When an assign is made to a function that return a vector the data on this vector is clean up immediately after the assign or it keep it until the last moment to receive the new data?
b) If the data is immediately destroyed, which state the vector during the function process to build the new data?
b.1) If the data has kept, that means I can have in memory two huge vectors (the old data and new data) until the assign be made (returned)?
c) And what about the move semantic? It try to use the space already created? (if the data is not destroyed immediately like asked in the first question)
To better demonstrate it I wrote a tiny program:
#include <vector>
#include <string>
using namespace std;
vector<string> func2() {
vector<string> f2(200000, string(20,'a'));
return f2;
}
vector<string> func4() {
vector<string> f4(400000, string(40,'b'));
//Now I have in memory 400000X40 + 200000X20?
return f4;
//after assignment I know I have just f4 content
}
vector<string> func1() {
vector<string> f1(100000, string(10,'c'));
return f10;
}
int main() {
vector<string> mVec;
mVec = func2(); //Create internally a vector with 20 units string with 20 'b' inside
mVec = func4(); //Create internally a vector with 40 units string with 40 'b' inside
mVec = func1(); //Create internally a vector with 10 units string with 10 'b' inside
return 0;
}
If the move semantic really use the existent space, how it works when mVec has less data and need to assign more (func2 to func4) or vice-versa (func4 to func1).
When func4() is called, right before return statement, you surely have two big vectors. And you have them in memory right up to the point of assignment.
As for c), vector is contigous container, so when you create new vector, it will be stored in memory as a whole, not one part in memory block 1 and the other part in memory block 127 (just an example).
My suggestion would be, to use passing vector (which will be refiled) by reference, and resize it correctly before filling, that way you may avoid asignment of whole vector.
Code sample (optimization suggestion):
#include <vector>
#include <algorithm> // std::fill
#include <string>
using namespace std;
void func2(vector<string>& vec) {
vec.resize(200000);
fill(vec.begin(), vec.end(), string(20, 'a'));
}
void func4(vector<string>& vec) {
vec.resize(400000);
fill(vec.begin(), vec.end(), string(40, 'b'));
}
void func1(vector<string>& vec) {
vec.resize(100000);
fill(vec.begin(), vec.end(), string(10, 'c'));
}
int main() {
vector<string> mVec;
func2(mVec); //Create internally a vector with 20 units string with 20 'b' inside
func4(mVec); //Create internally a vector with 40 units string with 40 'b' inside
func1(mVec); //Create internally a vector with 10 units string with 10 'b' inside
return 0;
}

cannot access the vector members of a class

I have tried to access the members of a class Part that are vector elements of type integer inside the vector tasks.
#include <iostream>
#include <vector>
using namespace std;
class Part{
vector<int> tasks;
public:
void setTasks(void);
void getTasks(void);
};
void Part::setTasks(void){
vector<int>::iterator it;
int i=1;
for (it = this->tasks.begin(); it != this->tasks.end(); ++it)
{
*it=i;
i=i+1;
}
}
void Part::getTasks(void){
vector<int>::iterator it;
for (it = this->tasks.begin(); it != this->tasks.end(); ++it)
cout<<*it<<"\t";
}
int main()
{
Part one;
one.setTasks();
one.getTasks();
return 0;
}
I am simply trying to access the values and print them yet failing. There is no compilation error. In run-time, nothing is outputted in the terminal. Where is the error?
A default constructed vector has zero size, so the for loop in setTasks is never entered (since the begin() and end() iterators are the same at that point). If you set an initial size to the vector your code will work as intended. For instance, try adding the following at the beginning of setTasks
tasks.resize(10); // sets vector size to 10 elements, each initialized to 0
Another way to write that function would be
#include <numeric>
...
void Part::setTasks(void){
tasks.resize(10);
std::iota(tasks.begin(), tasks.end(), 1); // requires C++11
}
You could also set the initial size of the vector in the default constructor of Part if you wanted to. In that case add the following public constructor
Part() : tasks(10)
{}
Yet another way to achieve setting the size upon construction would be
class Part{
vector<int> tasks = vector<int>(10); // requires C++11
The size of your vector is 0 when you call setTasks(). Your iterator doesn't get you into the for loop at all. You need to think about what exactly you want your setTasks() to do. How many elements of the vector did you intend to set? You should either define your vector with that size, or use that many number of push_backs instead to set your vector to the desired value.
Your vector is empty. Try giving it a size. For example, vector<int> tasks(10). See option 3 in this.
Alternatively, you can use a "back-insert" iterator (#include <iterator>), which internally calls std::vector::push_back, like this:
void Part::setTasks(void){
auto back_it = std::back_inserter(tasks);
for(int i = 0; i < 10; ++i)
*back_it++ = i;
}
This kind of iterator is especially useful in algorithms where your destination size is unknown. Although if you know the size in advance, you should use reserve/resize or specify the size at construction, since push-ing back into a vector can sometimes be slow due to re-allocation.

2D vector specific element pass to a function

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.

How to convert vector to set?

I have a vector, in which I save objects. I need to convert it to set. I have been reading about sets, but I still have a couple of questions:
How to correctly initialize it? Honestly, some tutorials say it is fine to initialize it like set<ObjectName> something. Others say that you need an iterator there too, like set<Iterator, ObjectName> something.
How to insert them correctly. Again, is it enough to just write something.insert(object) and that's all?
How to get a specific object (for example, an object which has a named variable in it, which is equal to "ben") from the set?
I have to convert the vector itself to be a set (a.k.a. I have to use a set rather than a vector).
Suppose you have a vector of strings, to convert it to a set you can:
std::vector<std::string> v;
std::set<std::string> s(v.begin(), v.end());
For other types, you must have operator< defined.
All of the answers so far have copied a vector to a set. Since you asked to 'convert' a vector to a set, I'll show a more optimized method which moves each element into a set instead of copying each element:
std::vector<T> v = /*...*/;
std::set<T> s(std::make_move_iterator(v.begin()),
std::make_move_iterator(v.end()));
Note, you need C++11 support for this.
You can initialize a set using the objects in a vector in the following manner:
vector<T> a;
... some stuff ...
set<T> s(a.begin(), a.end());
This is the easy part. Now, you have to realize that in order to have elements stored in a set, you need to have bool operator<(const T&a, const T& b) operator overloaded. Also in a set you can have no more then one element with a given value acording to the operator definition. So in the set s you can not have two elements for which neither operator<(a,b) nor operator<(b,a) is true. As long as you know and realize that you should be good to go.
If all you want to do is store the elements you already have in a vector, in a set:
std::vector<int> vec;
// fill the vector
std::set<int> myset(vec.begin(), vec.end());
You haven't told us much about your objects, but suppose you have a class like this:
class Thing
{
public:
int n;
double x;
string name;
};
You want to put some Things into a set, so you try this:
Thing A;
set<Thing> S;
S.insert(A);
This fails, because sets are sorted, and there's no way to sort Things, because there's no way to compare two of them. You must provide either an operator<:
class Thing
{
public:
int n;
double x;
string name;
bool operator<(const Thing &Other) const;
};
bool Thing::operator<(const Thing &Other) const
{
return(Other.n<n);
}
...
set<Thing> S;
or a comparison function object:
class Thing
{
public:
int n;
double x;
string name;
};
struct ltThing
{
bool operator()(const Thing &T1, const Thing &T2) const
{
return(T1.x < T2.x);
}
};
...
set<Thing, ltThing> S;
To find the Thing whose name is "ben", you can iterate over the set, but it would really help if you told us more specifically what you want to do.
How to correctly initialize it?
std::set<YourType> set;
The only condition is that YourType must have bool operator<(const YourType&) const and by copyable (default constructor + assignment operator). For std::vector copyable is enough.
How to insert them correctly.
set.insert(my_elem);
How to get specific object (for example object, which has name variable in it, which is equal to "ben") from set?
That's maybe the point. A set is just a bunch of object, if you can just check that an object is inside or iterate throught the whole set.
Creating a set is just like creating a vector. Where you have
std::vector<int> my_vec;
(or some other type rather than int) replace it with
std::set<int> my_set;
To add elements to the set, use insert:
my_set.insert(3);
my_set.insert(2);
my_set.insert(1);

Erasing elements of Deque container

I want to erase the elements of a deque. When you have a deque that contain structs and you want to print the elements from back to front, but you don't want to print elements that have the same struct elements how do you do it?
I have a struct like this:
struct New_Array {
array<array<int,4>,4> mytable;
int h;
};
The deque is filled with elements from a previous procedure.
You want to print all the elements that are in the deque, but each table you print must have a unique "h". Only the first table you find with a specific "h" must be printed, the other tables with the same "h" should not be printed. I think this can be also inplemented with a "find" function.
The value of "h" that we will find starting from the back of the deque will be 0 and it will increase its value towards the front of the deque.
I have tried this:
void Find_Solution_Path(deque<New_Array> Mydeque)
{
while(Mydeque.size()>0)
{
New_Array y=Mydeque.back();
PrintBoard(y); //this is a function that prints the 4x4 array.
Mydeque.pop_back();
for(unsigned int i=0; i<Mydeque.size(); i++)
{
New_Array xxx=Mydeque[i];
if(xxx.h==y.h)
{
Mydeque.erase(Mydeque[i]);
}
}
}
}
I would not use a deque but a set. If you absolutely need the deque, create a set none the less. Define a < operator with an appropriate criterion < reflecting the uniqueness. You insert each printed element into the set. Before printing you check if the element is already present in the set (find).
HTH, Martin
One way is to use std::unique_copy.
#include <iostream>
#include <algorithm>
#include <iterator>
#include <deque>
struct New_Array {
array<array<int,4>,4> mytable;
int h;
// unique_copy needs this:
bool operator==(const New_Array& other) { return h == other.h; }
};
ostream& operator<<(ostream& out, const New_Array& v)
{
return out << v.h;
}
int main()
{
std::deque<New_Array> q;
New_Array temp;
// {1, 1, 2, 2, 3, 3}
temp.h = 1;
q.push_back(temp);
q.push_back(temp);
temp.h = 2;
q.push_back(temp);
q.push_back(temp);
temp.h = 3;
q.push_back(temp);
q.push_back(temp);
unique_copy(q.begin(), q.end(), ostream_iterator<New_Array>(cout, "\n"));
}
The range needs to be sorted for unique_copy to work properly. Sorting isn't needed in above case since we inserted elements in order.
I believe #Martin answer is probably the best solution. If you cannot change the signature for the function returning a deque, you can just construct a set from it and all the duplicates will automatically go away:
// First you need to declare a compare function for NewArray objects
struct NewArrayComp {
bool operator()(const NewArray& a1, const NewArray& a2) const {
return a1.h < a2.h;
}
};
// Then you can construct a set from the deque
deque<NewArray> dq;
// ...
std::set<NewArray, NewArrayComp> s(dq.begin(), dq.end());
// Finally you can just print the arrays (without duplicates)
for (const auto& a : s)
PrintBoard(a);
This solution has a O(n log n) complexity, while your code is O(n^2).
Additionally, if you do not want to pay the cost of duplicating the elements from the deque into the set you can use move semantics in C++11:
std::set<NewArray, NewArrayComp> s;
std::move(dq.begin(), dq.end(), std::inserter(s, s.begin()));
This will just move all the elements without making copies of them.