C++ invalid operator< when using sorting - c++

bool sortingGame(Player Player1, Player Player2)
{
if (Player1.gamePercent() > Player2.gamePercent())// first compare precetage (float)
{
return true;
}
else if (Player2.gamePercent() > Player1.gamePercent())
{
return false;
}
else if (Player1.getLastName() > Player2.getLastName())//then names (std::string)
{
return true;
}
else if (Player2.getLastName() > Player1.getLastName())
{
return false;
}
else if (Player1.getFirstName() > Player2.getFirstName())
{
return true;
}
else
{
return false;
}
}
heres in main():
sort(Players.begin(), Players.end(), sortingGame);
Here is the error showed when debugging in Visual Studio.
Program:C:\.....\include\algorithm
Line:3014
Expression: invalid operator<

When I mockup a players class and run your code it works fine. The error must belong somewhere else.
However your code could be tightened up considerably, by checking for equality and return the result of the comparison:
bool sortingGame(Player Player1, Player Player2)
{
if (Player1.gamePercent() != Player2.gamePercent())// first compare precetage (float)
{
return Player1.gamePercent() > Player2.gamePercent();
}
else if (Player1.getLastName() != Player2.getLastName())
{
return Player1.getLastName() > Player2.getLastName();
}
else
{
return Player1.getFirstName() > Player2.getFirstName();
}
}
Consider as well that strings are usually listed in reverse sort order(alphabetical). Therefore the less than operator(<) would work better:
bool sortingGame(Player Player1, Player Player2)
{
if (Player1.gamePercent() != Player2.gamePercent())// first compare precetage (float)
{
return Player1.gamePercent() > Player2.gamePercent();
}
else if (Player1.getLastName() != Player2.getLastName())
{
return Player1.getLastName() < Player2.getLastName();
}
else
{
return Player1.getFirstName() < Player2.getFirstName();
}
}

Related

Can this get to the end of the function and not return anything?

I am making a c++ text based game and while making a feature for eating food I made this function names eating. I am getting a warning saying its possible to reach the end with no return value. How is it possible to get to the end and not return something?
int inventory::eat(std::string eating)
{
if (!consumables.empty())
{
for (int i = 0; i < consumables.size(); i++)
{
if (consumables[i].name == eating)
{
return consumables[i].effect;
}
else
{
return 404;
}
}
}
else
{
return 505;
}
}
Presumably the compiler is unable to tell that if consumables.empty() == false, then consumables.size() > 0.
I'd probably rewrite it as this, but I'm worried about the if/else inside your for loop.
int inventory::eat(std::string eating) {
for (int i = 0; i < consumables.size(); i++) {
if (consumables[i].name == eating) {
return consumables[i].effect;
} else {
return 404;
}
}
return 505;
}
Assuming no other thread modifies consumables while eat() is running, then no, return will not be skipped. But the compiler doesn't know that. It doesn't knower that !empty() and size() > 0 mean the same thing for a container. They are just two separate method calls.
That said, I would suggest writing the code more like this, which is easier to read, and avoids the warning:
int inventory::eat(const std::string &eating)
{
if (consumables.empty())
return 505;
for (int i = 0; i < consumables.size(); ++i)
{
if (consumables[i].name == eating)
return consumables[i].effect;
}
return 404;
}
Or, if you are using C++11 and consumables supports iterators:
#include <algorithm>
int inventory::eat(const std::string &eating)
{
if (consumables.empty())
return 505;
auto found = std::find_if(
consumables.begin(), consumables.end(),
// replace 'consumable' below with your actual type name as needed...
[&](const consumable &c){ return c.name == eating; }
);
if (found != consumables.end())
return found->effect;
return 404;
}

Error: control may reach end of non-void function in C++

I cannot figure out why this error is happening: error: "control may reach end of non-void function" even when "else" statement is present at the end.
Here is the code:
bnode* binsert(bnode *h,int k){
bnode *temp=new bnode;
if(h==NULL)
{
temp->num=k;
temp->L=NULL;
temp->R=NULL;
h=temp;
return h;
}
else if(h->L==NULL && k<h->num)
{
temp->num=k;
temp->L=NULL;
temp->R=NULL;
h->L=temp;
return h;
}
else if(h->R==NULL && k>h->num)
{
temp->num=k;
temp->L=NULL;
temp->R=NULL;
h->R=temp;
return h;
}
else if(h->L!=NULL && k<h->num)
{
h->L=binsert(h->L,k);
}
else
{
h->R=binsert(h->R,k);
}
}
You need to return the results of recursive calls, it's not done automatically.
You can also simplify your code a bit by adding a constructor:
bnode::bnode(int v)
: num(v),
L(nullptr),
R(nullptr)
{
}
and since you're already handling the case of a null parameter, you don't need special cases for null children:
bnode* binsert(bnode *h,int k)
{
if(h == nullptr)
{
h = new bnode(k);
}
else if(k < h->num)
{
h->L = binsert(h->L, k);
}
else if(k > h->num)
{
h->R = binsert(h->R, k);
}
return h;
}
because this last 2 conditions:
else if(h->L!=NULL && k<h->num)
{
h->L=binsert(h->L,k);
}
else
{
h->R=binsert(h->R,k);
}
may occur and no return is given...
you need to be sure the function returns a value no matter what the condition evaluates....
else if(h->L!=NULL && k<h->num)
{
h->L=binsert(h->L,k);
}
else
{
h->R=binsert(h->R,k);
}
In the else if and else cases for your code, if you reach here, you do not return a value, and the behavior is undefined if you try to use this value.
You probably want to add a return h; in the two branches.

Best way to check if one of other objects is true or not

I am looking for best way to implement this scenario:
I have 4 objects that have Boolean member that in the flow of the app sometimes they are set to true and sometimes are set to false depending on conditions;
Then I have final function that gets 1 of this objects and needs to check if in the other 3 objects one of them has the member set to true .
The problem is I know how to do the dirty check , and I am searching for cleaner way here is my code for the final function:
class Obj
{
public :
Obj(int _id) : id(_id)
bool status;
int id // only 4 objects are created 0,1,2,3
}
m_obj0 = new Obj(0) ;
m_obj1 = new Obj(1) ;
m_obj2 = new Obj(2) ;
m_obj3 = new Obj(3) ;
bool check(Obj* obj)
{
if(obj->id == 0)
{
if(m_obj1->status || m_obj2->status || m_obj3->status)
{
return true;
}
return false;
}else if(obj->id == 1)(
if(m_obj0->status || m_obj2->status || m_obj3->status)
{
return true;
}
return false;
}else if(obj->id == 2)(
if(m_obj0->status || m_obj1->status || m_obj3->status)
{
return true;
}
return false;
}else if(obj->id == 3)(
if(m_obj0->status || m_obj1->status || m_obj2->status)
{
return true;
}
return false;
}
is there a shorter and cleaner way to accomplish this check function ?
You can set m_obj as an array. Then use a for loop to check
bool check(Obj* obj)
{
for (int i = 0; i < 4; i ++) {
if (obj->id == i) continue;
if (m_obj[i]->status == true)
return true;
}
return false;
}
Or add them together, then subtract m_obj[obj->id]->status。Check the result is zero or not
bool check(Obj* obj)
{
int result = m_obj[0]->status+m_obj[1]->statusm_obj[2]->status
+m_obj[3]->status-m_obj[obj->id]->status;
return (result!=0);
}

C++ sorting array => vector iterators incompatible

I have a simple struct
struct test
{
std::vector<Data> data;
void sort()
{
std::sort(data.begin(), data.end());
}
}
Data is a struct as well and has only simple fields and implements a < operator like following:
EDIT: changes according to feedbacks are included
struct Data
{
// ADAPTION 1 - comparator works with reference now
bool operator<(const Data &data) const
// bool operator<(const Data data)
{
// 1) sortieren nach Typ
if (type < data.type)
return true;
else if (type > data.type)
return false;
// 2) nach name sortieren
if(strlen(strName) > 0)
{
if (strncmp(strName, data.strName, 50) < 0)
return true;
else if (strncmp(strName, data.strName, 50) > 0)
return false;
}
// ADAPTION 2 - added:
else if (data.strName[0]) // at least 1 character...
return true;
// 3) nach Spezialtyp sortieren
if(strlen(typeSpecial)>0)
{
if (strncmp(typeSpecial, data.typeSpecial, 50) < 0)
return true;
else if (strncmp(typeSpecial, data.typeSpecial, 50) > 0)
return false;
}
// ADAPTION 3 - added:
else if (data.strName[0]) // at least 1 character...
return true;
return false;
}
}
That's it. How can I get the vector iterators incompatible error that way? I'm not copying any vector, I'm directly calling the sort function with the vector...
In Visual Studio 2005, I've never had a problem, in Visual Studio 2012 this problem appeared and I don't know why and how to avoid it
There're a few issues with your code:
bool operator<(const Data data)
...should be...
bool operator<(const Data& data) const
Then:
if(strlen(strName) > 0)
{
if (strncmp(strName, data.strName, 50) < 0)
return true;
else if (strncmp(strName, data.strName, 50) > 0)
return false;
}
...needs...
else if (data.strName[0]) // at least 1 character...
return true;
This is required to ensure strict weak ordering, which is a requirement of std::sort's and means that when a < b, !(b < a).
Similarly:
if(strlen(typeSpecial)>0)
{
if (strncmp(typeSpecial, data.typeSpecial, 50) < 0)
return true;
else if (strncmp(typeSpecial, data.typeSpecial, 50) > 0)
return false;
}
...needs...
else if (data.typeSpecial[0])
return true;
Your string comparisons would be much cleaner if you used std::strings. If you do stick with ASCIIZ data, it would be better to use e.g. sizeof typeSpecial instead of 50 etc.. You can improve performance and code concision by doing less comparisons and trusting strncmp to handle empty strings appropriately (which it will):
if (type < data.Type) return true;
if (type > data.Type) return false;
int d = strncmp(strName, data.strName, sizeof strName);
if (d == 0)
d = strncmp(typeSpecial, data.typeSpecial, sizeof typeSpecial);
return d < 0;

C++ returning boolean as 95

Problem with returning booleans in c++..
bool find( const TrieNode &node, const string word )
{
if (word.length() == 0)
{
if (node.isWord)
{
cout << "TRUE" << endl;
return true;
}
else
{
cout << "FALSE" << endl;
return false;
}
}
char firstletter = word.at(0);
int index = firstletter - 'a';
if (node.letters[index] == NULL)
{
return false;
}
else
{
find (*node.letters[index],word.substr(1,(word.length() - 1)));
}
}
in my main I have
cout << find(*mynode,"word") << endl;
would yield to :
FALSE
95
clearly, a cout of FALSE means that the function returns false.. However, when I print out the result of the function, I get 95 which evaluates to true.. Any reason why it could be doing this?
thanks
Your missing a final return statement, so your getting whatever is in the low byte of EAX, which is random garbage. your probably want return true; at the very end of your function.
Your should pump the warning level of your compiler as it should be telling you this (something along the lines of "not all control paths return a value").
The problem is with your final if statement:
if (node.letters[index] == NULL) {
return false;
}
else {
//if execution gets here, the return value of the function is undefined
find (*node.letters[index],word.substr(1,(word.length() - 1)));
}
...perhaps try:
if (node.letters[index] == NULL) {
return false;
}
else {
return find (*node.letters[index],word.substr(1,(word.length() - 1)));
}