How to find integer in container which stores pointers? - c++

A container stores pointers to integers. I would like to find integer=66 using normal variable.
When I am trying to do this by pointer it is ok.
Code:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main ()
{
int *a=new int(22);
int *b=new int(44);
int *c=new int(66);
int d = 66;
vector<int*> v1;
v1.push_back(a);
v1.push_back(b);
v1.push_back(c);
std::vector<int*>::iterator it;
// it = find (v1.begin(), v1.end(), c); // Ok.
it = find (v1.begin(), v1.end(), d);
if (it != v1.end())
{
std::cout << "Element found in myvector: " << **it << '\n';
}
else
{
std::cout << "Element not found in myvector\n";
}
return 0;
}
I was trying to use find_if() function.

You could use a lambda function like this:
std::find_if(
std::begin(pointer_vec), std::end(pointer_vec),
[](const int *p){return p != nullptr && *p == 66;});

In C++11 you can do this:
it = find_if (v1.begin(), v1.end(), [d](int* p){ return *p == d; });

Related

set_intersection with a custom set comparator

When I use the std::set_intersection function with a set that has custom comparator I don't get the expected result.
The follow code outputs that {5,9,7} intersect {9} is empty set. However if I just use the normal comparator I get {9}.
#include <iostream>
#include <cstdlib>
#include <set>
using namespace std;
auto cmp = [](int* a, int* b) { return a < b; };
using stupid_set = set<int*, decltype(cmp)>;
int main() {
int* n5 = new int(5);
int* n9 = new int(9);
int* n7 = new int(7);
stupid_set s0 {n5, n9, n7};
stupid_set s1 {n9};
stupid_set i;
for (auto s:s0) {
cout << "s0:" << *s << endl;
}
for (auto s:s1) {
cout << "s1:" << *s << endl;
}
set_intersection(s0.begin(), s0.end(), s1.begin(), s1.end(), std::inserter(i, i.begin()));
for (auto x : i) {
cout << "Int=" << *x << endl;
}
}
There are multiple problems with your code, but the core one is that you use a custom comparator for sets, but not for std::set_intersection function call. This function also needs to compare elements, and, of course, must compare them with the same comparator.
Use:
struct cmp
{
bool operator()(int* a, int* b) const { return *a < *b; };
};
using stupid_set = set<int*, cmp>;
and
set_intersection(
s0.begin(), s0.end(),
s1.begin(), s1.end(),
std::inserter(i, i.begin()),
cmp{} // custom comparator used for sets
);
Whole live demo is here: https://godbolt.org/z/OAr3xV.
Note that if you omit the comparator, std::set_intersection will use operator< for set elements, and this operation is generally undefined for pointers.
If you really want to compare pointers and not the integer values there point to, you need to use std::less, since this defines order even for pointers in general:
struct cmp
{
bool operator()(int* a, int* b) const { return std::less<int*>{}(a, b); };
};
Again, you need to pass this comparator to std::set_intersection as well.
Live demo: https://godbolt.org/z/tLdfqn.
You are mixing compare function passed to the std::set and std::set_intersection. When passed to the std::set, Compare function is used for sorting because it is key comparison function. When passed to std::set_intersection it is used to define an intersection.
Try following:
#include <iostream>
#include <cstdlib>
#include <set>
#include <algorithm>
struct cmp {
bool operator()(int *a, int *b) const {
return *a < *b;
}
};
using stupid_set = std::set<int*, cmp>;
int main() {
int* n5 = new int(5);
int* n9 = new int(9);
int* n7 = new int(7);
stupid_set s0 {n5, n9, n7};
stupid_set s1 {n9};
stupid_set i;
for (auto s : s0) {
std::cout << "s0:" << *s << std::endl;
}
for (auto s:s1) {
std::cout << "s1:" << *s << std::endl;
}
std::set_intersection(
s0.begin(),
s0.end(),
s1.begin(),
s1.end(),
std::inserter(i, i.begin()),
cmp()
);
for (auto x : i) {
std::cout << "Int=" << *x << std::endl;
}
}
Check live

iterating over vector of vectors in c++

I've just started to code in C++, so i'm new to STL .
Here i'm trying to iterate over a graph stored as vector of vectors.
#include <iostream>
#include <vector>
#include <iostream>
using namespace std;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for (it = adj.begin(); it != adj.end(); it++)
{
cout << (*it) << endl;
if ((*it) == x)
for (i = (*it).begin(); i != (*it).end(); i++)
{
cout << (*i) << endl;
if ((*i) == y)
return 1;
}
}
return 0;
}
int main()
{
}
I'm getting an error std::vector<int> is not derived from const gnu cxx. Can someone point me in the right direction ?
*it pointing to vector not int that is why you are getting error
following code may work for you
#include <vector>
#include <iostream>
using namespace std;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for (it = adj.begin(); it != adj.end(); it++)
{
cout << (*(*it).begin()) << endl;
if (( (*(*it).begin())) == x)
for (i = (*it).begin(); i != (*it).end(); i++)
{
cout << (*i) << endl;
if ((*i) == y)
return 1;
}
}
return 0;
}
int main()
{
}
for accessing first element of the vector of the use
(*(*it).begin()) in place of (*it)
if you are studying graph then use array of vector. for more details please go through following url
C++ Depth First Search (DFS) Implementation
cout << (*it) << endl;
Here, you declared it as a:
vector<vector<int> >::iterator it;
Therefore, *it is a:
vector<int>
So you are attempting to use operator<< to send it to std::cout. This, obviously, will not work. This is equivalent to:
vector<int> v;
cout << v;
There is no operator<< overload that's defined for what cout is, and a vector<int>. As you know, in order to print the contents of a vector, you have to iterate over its individual values, and print its individual values.
So, whatever your intentions were, when you wrote:
cout << (*it) << endl;
you will need to do something else, keeping in mind that *it here is an entire vector<int>. Perhaps your intent is to iterate over the vector and print each int in the vector, but you're already doing it later.
Similarly:
if ((*it) == x)
This won't work either. As explained, *it is a vector<int>, which cannot be compared to a plain int.
It is not clear what your intentions are here. "Graph stored as a vector or vectors" is too vague.
The following code compiles with the option std=c++11. But x is missing in vector<vector<int>>. If adj had type vector<pair<int, vector<int>>> it would better match.
The following code compiles for vector<vector<int>> but it doesn't use x.
using std::vector;
using std::pair;
using std::cout;
using std::endl;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for(it=adj.begin();it!=adj.end();it++)
{
// cout << (*it) << endl;
for (const auto& nexts: *it)
cout << nexts << ' ';
cout << endl;
for(i=(*it).begin();i!=(*it).end();i++)
{
cout << (*i) << endl;
if((*i)==y)
return 1;
}
}
return 0;
}
This code compiles with <vector<pair<int, vector<int>>> and uses x.
using std::vector;
using std::pair;
using std::cout;
using std::endl;
int reach(vector<pair<int, vector<int> > > &adj, int x, int y) {
vector<pair<int, vector<int> > >::iterator it;
vector<int>::iterator i;
for(it=adj.begin();it!=adj.end();it++)
{
cout << it->first << endl;
if (it->first == x)
for(i=it->second.begin();i!=it->second.end();i++)
{
cout << (*i) << endl;
if((*i)==y)
return 1;
}
}
return 0;
}
Wrap it up in an iterator.
This can be templated for reuse.
Here is a minimal working example for the std::vector<T> container:
#include <iostream>
#include <utility>
#include <vector>
/// Iterable vector of vectors
/// (This just provides `begin` and `end for `Vector2Iterable<T>::Iterator`).
template<typename T>
class VovIterable
{
public:
static const std::vector<T> EMPTY_VECTOR;
/// Actual iterator
class Iterator
{
typename std::vector<std::vector<T>>::const_iterator _a1;
typename std::vector<T>::const_iterator _a2;
typename std::vector<std::vector<T>>::const_iterator _end;
public:
/// \param a1 Outer iterator
/// \param a2 Inner iterator
/// \param end End of outer iterator
explicit Iterator(typename std::vector<std::vector<T>>::const_iterator a1, typename std::vector<T>::const_iterator a2, typename std::vector<std::vector<T>>::const_iterator end)
: _a1(a1)
, _a2(a2)
, _end(end)
{
Check();
}
bool operator!=(const Iterator &b) const
{
return _a1 != b._a1 || _a2 != b._a2;
}
Iterator &operator++()
{
++_a2; // Increment secondary
Check();
return *this;
}
const T &operator*() const
{
return *_a2;
}
private:
void Check()
{
while (true)
{
if (_a2 != _a1->end()) // Is secondary live?
{
break;
}
// Increment primary
_a1++;
if (_a1 == _end) // Is primary dead?
{
_a2 = EMPTY_VECTOR.end();
break;
}
_a2 = _a1->begin(); // Reset secondary
}
}
};
private:
std::vector<std::vector<T>> _source;
public:
explicit VovIterable(std::vector<std::vector<T>> source)
: _source(std::move(source))
{
}
/// Start of vector of vectors
[[nodiscard]] Iterator begin() const
{
if (this->_source.empty())
{
return end();
}
return Iterator(this->_source.cbegin(), this->_source.cbegin()->cbegin(), this->_source.cend());
}
/// End of vector of vectors
[[nodiscard]] Iterator end() const
{
return Iterator(this->_source.cend(), EMPTY_VECTOR.end(), this->_source.cend());
}
};
template<typename T>
const std::vector<T> VovIterable<T>::EMPTY_VECTOR = {0};
/// Sample usage
int main()
{
std::vector<std::vector<int>> myVov{{1, 2, 3},
{4, 5, 6},
{7, 8, 9}};
for (int i: VovIterable(myVov))
{
std::cout << i << std::endl;
}
return 0;
}

prinvt content of vectors

Resolved, thanks all. The vector needs to be initialized.
I am new in c++. I appreciate it if you cuold help me print the content of the following vector v. Here is the code:
#include <stdio.h>
#include <vector>
#include <iostream>
int main(int argc, char **argv)
{
std::cout << "hello world\n";
std::vector<int>* v; (<-- std::vector<int>* v = new std::vector<int>();]
v->push_back(17);
v->push_back(12);
v->push_back(23);
v->push_back(42);
for(std::vector<int>::iterator it = v->begin(); it!= v->end(); ++it) {
std::cout << *it << "\n";
}
std::cout <<"done\n";
return 0;
}
You missed to allocate memory for your vector pointer. I'd rather recommend just using a variable allocated on the stack:
#include <stdio.h>
#include <vector>
#include <iostream>
int main(int argc, char **argv)
{
std::cout << "hello world\n";
std::vector<int> v; // <<<<< Note that * was omitted here
v.push_back(17);
v.push_back(12);
v.push_back(23);
v.push_back(42);
for(std::vector<int>::iterator it = v.begin(); it!= v.end(); ++it) {
std::cout << *it << "\n";
}
std::cout <<"done\n";
return 0;
}
See the Live Demo.
As for your edit:
v will be used as follows:
void AddItem(uint64_t fkey, vector<uint64_t>* v) {
v->push_back(fkey);
}
Rather choose this signature:
void AddItem(uint64_t fkey, vector<uint64_t>& v) {
// ^ << Choose a reference
v.push_back(fkey);
// ^ << dereference accordingly
}
No need to make v a pointer here, use something like this instead:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::vector<int> v;
// push_back data...
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout,","));
}
This will print out the contents of v from beginning to end separated by , chars.
If you really want to make v a pointer to a std::vector though, then try the following:
int main() {
std::vector<int>* v = new std::vector<int>(); // allocate memory on heap
v->push_back(17);
// etc...
std::copy(v->begin(), v->end(), std::ostream_iterator<int>(std::cout,","));
delete v; // make sure to delete from heap to prevent memory leak
}
I'm assuming this is not real code because there is no good reason to use a pointer to a vector in this case and the pointer doesn't point at anything.
But if your question is just how to print the contents of a vector given a pointer then you can simply dereference the pointer and use a range-based for loop.
#include <vector>
#include <iostream>
void print(std::vector<int>* v) {
for(int value : *v)
std::cout << value << "\n";
}
int main() {
std::cout << "hello world\n";
std::vector<int> v = {17, 12, 23, 42};
print(&v);
std::cout <<"done\n";
}
Live demo.

how to get the first non NULL value in a MAP?

i have an STL map ;
i would like to get the first non NULL value in the map;
is there an efficient/quick way to do that?
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
bool IsNotNull(const pair<const int, int>& i)
{
return i.second != 0;
}
int main() {
map<int, int> m;
m[0] = 0;
m[1] = 1;
map<int, int>::const_iterator it = find_if(m.begin(), m.end(), IsNotNull);
cout << it->second << endl;
return 0;
}
Ideone demo
There's nothing quicker than just looping through and finding what you're looking for
for (map<X,Y>::const_iterator i = m.begin(); i != m.end(); ++i)
{
if (i->second != NULL)
{
// do something with first non-NULL value
break;
}
}

Storing values from a vector to a string as comma seperated values

how can I store the values returned from a function to a string as comma seperated values. Can anyone help me..?
const myVector &vecList = obj.get_List();
vector<myNumVector *>::const_iterator iter;
for (iter= vecList.begin(); iter!= vecList.end(); iter++)
{
string myNum = (*iter)->get_myNum();
string myNumList = ?
//myNumList should be = drt123,ret34,dfghgd234.... if these are the return values
} //can we achive this by use of some sting functions..?
As can be seen from the links I posted, there are lots of ways to do this. Here is, I believe, the simplest:
#include <vector>
using std::vector;
#include <string>
using std::string;
#include <boost/assign/list_of.hpp>
using boost::assign::list_of;
namespace ba = boost::assign;
vector<string> victor = list_of
("Clarence Oveur")
("Roger Murdock")
("Victor Basta");
int main() {
string result;
for(vector<string>::iterator it = victor.begin();
it != victor.end();
++it) {
if(it != victor.begin()) {
result += ", ";
}
result += *it;
}
cout << result << "\n";
}
EDIT: To translate directly to OP's question:
const myVector &vecList = obj.get_List();
vector<myNumVector *>::const_iterator iter;
string myNumlist;
for (iter= vecList.begin(); iter!= vecList.end(); iter++)
{
string myNum = (*iter)->get_myNum();
if(iter!=vecList.begin()) {
nyNumList += ",";
}
myNumList += myNum;
}
EDIT: Simplified by removing bool first from previous solution.
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
int main () {
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
std::stringstream list;
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(list, ","));
std::cout << list.str();
return 0;
}
Outputs: 1,2,3,4,
more modern approach, also solving the trailing ","
#include <string>
#include <numeric>
#include <iostream>
int main() {
const auto v = {1, 2, 3, 4};
const auto list = std::accumulate(begin(v), end(v), std::string{}, [](const std::string& so_far, const auto& next) {
return so_far + (so_far.empty() ? "" : ", ") + std::to_string(next);
});
std::cout << list;
return 0;
}
Yes, this can be achieved using string functions, along with a handful other methods.
Given a string myNumList defined outside the loop, you could simply
myNumList += "," + myNum;
although that would add an extraneous comma in the beinning, so check if iter is pointing there first:
if(iter != vecList.begin())
myNumList += ',';
myNumList += myNum;