Find if structures with same values exist in vector array - c++

I want to check if there are structures with the same values in the vector array. May someone explain to me how should I do this?
struct mineCoordinate{
int x;
int y;
};
std::vector<mineCoordinate> mines; // vector array
if(std::find(mines.begin(), mines.end(), mineCoordinate{userInputX,userInputY}) != mines.end()) {
//do something if true.}
As you can see I tried std::find function, and I think it should work (
this is the answer to most of these questions like mine). The only condition was to compare the same objects

What seems to be missing from your code is a definition of what it means for two of your mineCoordinate objects to be equal. If you add this
bool operator==(const mineCoordinate& a, const mineCoordinate& b)
{
return a.x == b.x && a.y == b.y;
}
then I think it will work too.
You might have thought that this definition is so obvious that it doesn't need to be explicitly defined, but that is not correct.

If you are using C++20, can you default the == operator:
struct mineCoordinate
{
int x;
int y;
bool operator==(const mineCoordinate&) const = default;
};

Related

Comparison Operator for Structure key in C++ Map

#include<bits/stdc++.h>
using namespace std;
struct segment{
int a;
int b;
int c;
bool const operator<(const segment &o) const {
return a < o.a;
}
};
int main()
{
map<segment,int> myMap;
map<segment,int>::iterator it;
struct segment x,y,z;
x.a=2;
x.b=4;
x.c=6;
y.a=2;
y.b=5;
y.c=8;
z.a=2;
z.b=4;
z.c=6;
myMap[y]++;
myMap[z]++;
myMap[x]++;
for( it =myMap.begin(); it != myMap.end(); it++)
cout<<(*it).first.a<<" "<<(*it).second<<endl;
return 0;
}
it gives result as
2 3
but i want it to print
2 1
2 2
In short I want to increment the value of the map if exactly the same struct instance is fed instead of making a new copy
IMO the best way to compare multiple members is using std::tie as it is much harder to mess up:
bool const operator<(const segment &o) const {
return std::tie(a, b, c) < std::tie(o.a, o.b, o.c);
}
Edit: Would just like to add this link to cppreference as the example there is almost exactly your question.
You can change your less operator to:
bool const operator<(const segment &o) const {
return a < o.a || (a == o.a && b < o.b) || (a==o.a && b==o.b && c < o.c) ;
}
This compares the values in the order of a, b, c.
But you can change it anyway you want to compare the structure.
As far as your map is concerned, there is only one unique object here. In terms of the comparison you specified, and the implied equivalence, x == y and y == z. Why? Neither of them is smaller than the other, so, according to STL logic by comparison, they must be equivalent.
Perhaps you're looking for a std::multimap.
Alternatively, if you want to define inequality (and hence implied equivalence) in terms of all the members, you could do something like this:
#include <tuple>
bool const operator<(const segment &o) const {
return std::make_tuple(a, b, c) < std::make_tuple(o.a, o.b, o.c);
}
P.S. You should avoid including stuff from bits, as you're including stuff from the implementation. Instead, try to use stuff like
// See? no bits.
#include <map>

Check if structure is not in vector

I have a vector of structs. I need to check if the struct is or is not in the vector. The entire struct, not any specific member. It throws me this error upon compile time:
binary '==' : no operator found which takes a left-hand operand of type 'NavigationNode'
(or there is no acceptable conversion)
My struct:
struct NavigationNode{
int x, y; //their x and y position on the grid
float f, g, h;
int parentGCost;
int value;
};
NavigationNode currentNode;
The vector
vector<NavigationNode> openList;
My find:
if (find(closedList.begin(), closedList.end(), currentNode) == closedList.end() )
{
}
You need to overload operator==.
As global function:
bool operator==( const NavigationNode& lhs, const NavigationNode& rhs )
{
// compare lhs and rhs
}
Or as member function:
bool operator==( const NavigationNode& other ) const
{
// compare this & other
}
You will have to write an equality operator for your custom type. Assuming all variables have to be the same for two NavigationNode objects to be the same, it should look something like this:
bool floatEqual(float a, float b)
{
// adapt this comparison to fit your use-case - see the notes below
static const int EPSILON = 0.00001; // arbitrarily chosen - needs to be adapted to the occuring values!
return std::abs(a – b) <= EPSILON;
}
bool operator==(NavigationNode const & a, NavigationNode const & b)
{
return a.x == b.x &&
a.y == b.y &&
floatEqual(a.f, b.f) &&
floatEqual(a.g, b.g) &&
floatEqual(a.h, b.h) &&
a.parentGCost == b.parentGCost &&
a.value == b.value;
}
Even if you could also do it as a member function of NavigationNode, the recommended way is to implement the operator== as a free function (that way, both parameters can take advantage of any possible implicit conversions).
Note on float comparison: Due to how floating point numbers are represented, it is not a trivial task to compare them. Just checking for equality might not give the desired results. See e.g. this question for details:
What is the most effective way for float and double comparison?
You need to overload the comparison operator.
If your intention of "==" is "are each of the values contained in my struct equal to the corresponding members in this other struct" then you can write that.
bool operator==(const NavigationNode& lhs, const NavigationNode& rhs)
{
return /* compare each member in here */
}

C++ two priority sorting with multiset

I am trying to obtain a sorting of class objects according to two of its members in such a way: sort according to a member. If two objects have the same value (or if the difference is below some threshold) then search according to the member b. I am using multiset with that.
Problem is, that when another object comes, is checked according to sorting class, and fulfills to return true (to be put higher than the object that is compared to), it might also fulfill with another one being one step higher. How can I introduce here, that it should check with as many previous objects, and go as high as is only possible? (to obtain really well sorted multiset!)
Below how I wrote the sorting class. Please provide me with some nice idea!
And I had problems to introduce indentations for this part of code, anyone can help me to edit please? it's unreadable.
std::multiset<classA , classA ::SortClass> mydata;
class SortClass
{
public:
bool operator() (const classA &pt1, const classA &pt2)
{
if(pt1.a < pt2.a)
{
if(abs(pt1.a-pt2.a) < 0.01)
{
if(pt1.b > pt2.b)
return true;
else
return false;
}
else
return true;
}
else
return false;
}
};
EDIT:
Paste this and see what I want and cannot achieve. I want it sorted increasing with m_a and decreasing with m_b if m_a are the same (you can put there equality or inequality, does not work either)
#include <iostream>
#include <set>
using namespace std;
class classA
{
protected:
double m_b;
double m_a;
public:
double get_b() {return m_b;}
double get_a() {return m_a;}
void set_b(double b) {m_b = b;}
void set_a(double a) {m_a = a;}
class SortClass
{
public:
bool operator() (const classA &pt1, const classA &pt2)
{
if(pt1.m_a < pt2.m_a)
{
if(pt2.m_a - pt1.m_a == 0)
return (pt1.m_b > pt2.m_b);
else
return (pt1.m_a < pt2.m_a);
}
else
return false;
}
};
};
int main()
{
std::multiset<classA, classA::SortClass> mydata;
classA objA;
for(int i=0; i<100;i++)
{
objA.set_a(rand() %100);
objA.set_b(rand() %10);
mydata.insert(objA);
}
return 0;
}
Let's stop using true, and false and return the bool expressions. It make your code so much easier to read.
bool sortClassA (const classA &pt1, const classA &pt2)
{
if(pt2.m_a == pt1.m_a) {
return pt1.m_b > pt2.m_b;
}
return pt1.m_a > pt2.m_a;
};
Also, you created this issue you have with the threshold. Simple lower the threshold to something close to zero and the issue will go away, else you'll have to live with it. I don't see any other way.
Unfortunately, thresholds don't work well with STL ordered containers. A requisite for the ordering criterion is that it defines a strict weak ordering; this means, amongst other things, that if a == b and b == c, then a == b (== meaning here equivalent; this is, neither greater nor lesser than, not necessarily equal).
We might have pt1.a = 0.004, pt2.a = 0.01 and pt3.a = 0.016; according to your criterion, pt1.a == pt2.a and pt2.a == pt3.a, but pt1.a =\= pt3.a. Your ordering criterion does not meet the prerequisites for std::multiset and you cannot use it.

C++ std::sort with predicate function in Class

I want to sort vector of certain struct with certain order in certain class. I've wrote definition of struct and predicate function in a class and run std::sort in a method of the class with these struct and function. But compilation error has occurred. gcc version is 4.0.1 and OS is Mac OSX. The code is following:
class sample {
public:
struct s {
int x;
int y;
};
bool cmp (struct s a, struct s b) {
if (a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}
int func(void) {
std::vector <struct s> vec;
// ...
sort(vec.begin(), vec.end(), cmp); // compilation error
// ...
return 0;
}
};
int main(void) {
sample *smp = new sample();
smp->func();
return 0;
}
Error message was huge and complex. So this is first two lines of it.
sortSample.cpp: In member function 'int sample::func()':
sortSample.cpp:51: error: argument of type 'bool (sample::)(sample::s, sample::s)' does not match 'bool (sample::*)(sample::s, sample::s)'
...
Instead of above approach, the code could run correctly with following ways.
Define struct s and function cmp()
outside of class sample.
Remove
function cmp() and define operator
overloading of < in struct s.
Sample code of each approach is bellow.
1)
struct s {
int x;
int y;
};
bool cmp (struct s a, struct s b) {
if (a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}
class sample {
// ...
2)
struct s {
int x;
int y;
bool operator<(const struct s & a) const {
if (x == a.x)
return y < a.y;
else
return x < a.x;
}
};
Can anyone tell a mechanism of this behavior? Why does first approach invokes compilation error?
Thanks.
In the first case cmp is declared as a member function of the class sample and hence requires this pointer for calling it. Since the this pointer is not available compiler is complaining about it. You can make it work by declaring cmp as static function since static functions do not require this pointer for calling. In the second case, since cmp is declared as a stand-alone function again it will behave same as static function. In the third case (with overloaded operator), the sort algorithm will take care of calling the function for each object in the vector and hence it compiles.
Since cmp is not related to any particular instance of sample, make it a static member function.
The third approach which can be listed in your possibilities is using operator():
bool operator() (const s& a, const s& b) const
{
if (a.x == b.x)
return a.y < b.y;
else
return a.x < b.x;
}
sort(vec.begin(), vec.end(), *this);
I think defining cmp outside the class is best, because you should only make a function a member function when you need it to access some private feature in the class, and logically it feels right for it to be there. cmp is just a utility function that provides your class sample with functionality for its implementation, but it doesn't actually need to access private members. Furthermore, it's probably not going to be invoked in the context of an object (its only operations work on its parameters; nothing on the this pointer), nor must it be invoked in the context of a class sample::cmp. While it may seem like a trivial point, giving functions or code in general unnecessary breadth of access can be the start of the source of many a software bug or design convolution.
The added benefit of doing the above is that your invocation of std::sort will work, which answers your question.

C++ union array and vars?

There's no way to do something like this, in C++ is there?
union {
{
Scalar x, y;
}
Scalar v[2];
};
Where x == v[0] and y == v[1]?
Since you are using C++ and not C, and since they are of the same types, why not just make x a reference to v[0] and y a reference to v[1]
How about
union {
struct {
int x;
int y;
};
int v[2];
};
edit:
union a {
struct b { int first, second; } bee;
int v[2];
};
Ugly, but that's more accurate
Try this:
template<class T>
struct U1
{
U1();
T v[2];
T& x;
T& y;
};
template<class T>
U1<T>::U1()
:x(v[0])
,y(v[1])
{}
int main()
{
U1<int> data;
data.x = 1;
data.y = 2;
}
I've used something like this before. I'm not sure its 100% OK by the standard, but it seems to be OK with any compilers I've needed to use it on.
struct Vec2
{
float x;
float y;
float& operator[](int i) { return *(&x+i); }
};
You can add bounds checking etc to operator[] if you want ( you probably should want) and you can provide a const version of operator[] too.
If you're concerned about padding (and don't want to add the appropriate platform specific bits to force the struct to be unpadded) then you can use:
struct Vec2
{
float x;
float y;
float& operator[](int i) {
assert(i>=0);
assert(i<2);
return (i==0)?x:y;
}
const float& operator[](int i) const {
assert(i>=0);
assert(i<2);
return (i==0)?x:y;
}
};
I was looking for a similair thing and eventually came up with a solution.
I was looking to have a data storage object that I could use as both an array of values and as individual values (for end-user flexibility in writing Arduino libraries).
Here is what I came up with:
class data{
float _array[3];
public:
float& X = _array[0];
float& Y = _array[1];
float& Z = _array[2];
float& operator[](int index){
if (index >= 3) return _array[0]; //Make this action whatever you want...
return _array[index];
}
float* operator&(){return _array;}
};
int main(){
data Test_Vector;
Test_Vector[0] = 1.23; Test_Vector[1] = 2.34; Test_Vector[2] = 3.45;
cout<<"Member X = "<<Test_Vector.X;
cout<<"Member Y = "<<Test_Vector.Y;
cout<<"Member Z = "<<Test_Vector.Z;
float* vector_array = &Test_Vector;
cout<<"Array = {"<<vector_array[0]<<", "<<vector_array[1]<<", "<<vector_array[2]<<"}";
}
Thanks to Operator overloading, we can use the data object as if was an array and we can use it for pass-by-reference in function calls (just like an array)!
If someone with More C++ experience has a better way of applying this end product, I would love to see it!
EDIT: Changed up the code to be more cross-platform friendly
Given your example:
union
{
struct
{
Scalar x, y;
};
Scalar v[2];
};
As others have noted, in general, the standard does not guarantee that there will be no padding between x and y, and actually compilers inserting padding in structures is pretty common behavior.
On the other hand, with solutions like:
struct U
{
int v[2];
int& x;
int& y;
};
U::U()
: x(v[0])
, y(v[1])
{}
what I don't like mainly is the fact that I have to mention x, y twice. For cases where I have more than just a few elements (say 10), this becomes much less readable and harder to maintain - e.g. if you want to change the order of x,y then you have to change the indexes below too (well not mandatory but otherwise order in memory wouldn't match order of fields, which would not be recommended). Also, U can no longer be a POD since it needs a user-defined constructor. And finally, the x & y references consume additional memory.
Hence, the (acceptable for me) compromise I've come up with is:
struct Point
{
enum CoordType
{
X,
Y,
COUNT
};
int coords[CoordType::COUNT];
};
typedef Point::CoordType PtCoord;
With this you can then do:
Point p;
for ( int i = 0; i < PtCoord::COUNT; i++ )
p.coords[i] = 100;
std::cout << p.coords[PtCoord::X] << " " << p.coords[PtCoord::Y] << std::endl;
// 100 100
A bit sophisticated but I prefer this over the references suggestion.
Depending on what "Scalar" is, yes, you can do that in C++. The syntax is almost exactly (maybe even exactly exactly, but I'm rusty on unions) what you wrote in your example. It's the same as C, except there are restrictions on the types that can be in the unions (IIRC they must have a default constructor). Here's the relevant Wikipedia article.
With C++11 you have anonymous unions and structs which just export their definitions to the enclosing scope, so you can do this:
typedef int Scalar;
struct Vector
{
union
{
struct
{
Scalar x, y;
};
Scalar v[2];
};
};