Change comparison operators without large conditional block - c++

I am testing whether a number lies between two values. I leave it up to the user to choose whether the logical comparison should include an equal to on either (or both) of the limits or not.
They set this by defining a structwhich contains the two edge values and which comparison operator to use:
typedef struct {
double low;
double high;
bool low_equal; //false if a greater than operator (`>`) should be used, true if a greater-than-or-equal-to (`>=`) operator should be used
bool high_equal; //Same as low_equal but for a less-than operator
} Edges;
An array of Edges is created, (termed bins below) and for each input value I check whether it lies within the bin edges.
However, in order to use the desired pair of comparison operators, I've ended up with this hideous conditional block:
if (bins[j].low_equal && bins[j].high_equal)
{
if (value >= bins[j].low && value <= bins[j].high)
{
break;
}
}
else if (bins[j].low_equal)
{
if (value >= bins[j].low && value < bins[j].high)
{
data[i] = bins[j].value;
break;
}
}
else if (bins[j].high_equal)
{
if (datum > bins[j].low && datum <= bins[j].high)
{
break;
}
}
else
{
if (value > bins[j].low && value < bins[j].high)
{
break;
}
}
Is there a better way to do this? Can I somehow set the operators to use and then just call them?

A simple approach could be:
bool higher = (value > bins[j].low) || (bins[j].low_equal && value == bins[j].low);
bool lower = (value < bins[j].high) || (bins[j].high_equal && value == bins[j].high);
if (higher && lower)
{
// In range
}

you may use pointer on function
bool less(double lhs, double rhs) { return lhs < rhs; }
bool less_or_equal(double lhs, double rhs) { return lhs <= rhs; }
using comp_double = bool(double, double);
and then
comp_double *low_comp = bins[j].low_equal ? less_or_equal : less;
comp_double *high_comp = bins[j].high_equal ? less_or_equal : less;
if (low_comp(bins[j].low, value) && high_comp(value, bins[j].high)) {
// In range
}

This would be IMO a good case for the ternary operator
if ((bins[j].low_equal ? bins[j].low <= value : bins[j].low < value) &&
(bins[j].high_equal ? value <= bins[j].high : value < bins[j].high)) {
...
}

Related

C++ recursive struct comparator

I have created a struct to use as a key in a map to avoid having duplicate elements.
The struct contains pointers to children and siblings of its own type.
For the map, I have created a custom comparator that is supposed to recursively look at the element, the children and the siblings until a difference is found to make sure the elements are the same.
However, for some reason it is not working and Im still getting duplicates. After checking them out in the debugger, I concluded that they are indeed the exact same through and through so the problem must probably be somewhere in there.
This is the struct.
struct controlIdentifier
{
DWORD m_dwID;
DWORD m_dwDefaultID;
DWORD m_dwDisableID;
BYTE m_bType;
int m_nWidth;
int m_nHeight;
int m_nMargineH;
int m_nMargineV;
shared_ptr<controlIdentifier> m_pCHILD;
shared_ptr<controlIdentifier> m_pNEXT;
bool operator<(const controlIdentifier& id) const
{
if (m_dwDefaultID < id.m_dwDefaultID)
return true;
if (m_dwDisableID < id.m_dwDisableID)
return true;
if (m_bType < id.m_bType)
return true;
if (m_nWidth < id.m_nWidth)
return true;
if (m_nHeight < id.m_nHeight)
return true;
if (m_nMargineH < id.m_nMargineH)
return true;
if (m_nMargineV < id.m_nMargineV)
return true;
if (!m_pCHILD && id.m_pCHILD)
return true;
if (m_pCHILD && !id.m_pCHILD)
return false;
if (!m_pNEXT && id.m_pNEXT)
return true;
if (m_pNEXT && !id.m_pNEXT)
return false;
bool smaller = false;
if (m_pCHILD && id.m_pCHILD)
smaller = *m_pCHILD < *id.m_pCHILD;
if (!smaller)
{
if (m_pNEXT && id.m_pNEXT)
return *m_pNEXT < *id.m_pNEXT;
}
else
return smaller;
return false;
}
};
And this is how it's used.
struct cmpBySharedPtr {
bool operator()(const shared_ptr<controlIdentifier>& a, const shared_ptr<controlIdentifier>& b) const {
return *a < *b;
}
};
std::set<FRAMEDESC_SHAREDPTR> m_curFrames;
std::map<shared_ptr<controlIdentifier>, FRAMEDESC_SHAREDPTR, cmpBySharedPtr> m_serialFrames;
for (auto&& frame : m_curFrames)
{
shared_ptr<controlIdentifier> id;
makeIdentifiers(frame, id);
id->m_dwID = newId;
auto find = m_serialFrames.find(id);
if (find == m_serialFrames.end())
{
m_serialFrames.insert(std::pair(id, frame));
newId++;
}
}
m_dwID is not being compared on purspose.
Consider A = (child = 5, next = 6) and B = (child = 6, next = 5). Now A<B is true as (A.child < B.child) is true and it just returns that. Now consider B<A. B.child < A.child is false, so it checks the next fields.. Now B.next < A.next is true, so your comparison returns true.
So this is nonsensical -> A<B is true and B<A is true. This means your comparator is invalid.
The technical term for this is the comparator requires strict weak ordering - see https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings. Your comparator breaks the asymmetry requirement.
You can construct operator < by comparing field by field. But what you did is too little. Basically it shall look like this:
bool operator < (const A& left, const A& right)
{
if (left.firstField < right.firstField) return true;
if (right.firstField < left.firstField) return false; // this case is missing
if (left.secondField < right.secondField) return true;
if (right.secondField < left.secondField) return false; // this case is missing
....
return false;
}
You are missing cases when you can conclude, that for sure, left object is "greater" than right object.

infix to postfix program

I have written the following infix to postfix program but it's not working.
My program takes input but doesn't show any result. Can anyone help find the problem in my program.
And also it would be a great help if you tell if my Algorithm for converting infix to postfix is correct or not.
using namespace std;
class Stack
{
private:
int top;
char s[mx];
public:
Stack()
{
top=-1;
}
void push(char c)
{
if(!stackFull())
s[++top]=c;
}
void pop()
{
if(!stackEmpty())
top--;
else cout<<"Stack is empty"<<endl;
}
char topShow()
{
if(!stackEmpty())
return s[top];
}
bool stackEmpty()
{
if(top==-1)
return 1;
else return 0;
}
bool stackFull()
{
if(top == (mx-1))
return 1;
else return 0;
}
};
class Expression
{
private:
char entry2;
int precedence;
char infix[mx];
char postfix[mx];
public:
int prec(char symbol)
{
switch(symbol)
{
case '(':return 0; break;
case '-':return 1; break;
case '+':return 2; break;
case '*':return 3; break;
case '/':return 4; break;
}
}
void Read()
{
cout<<"Enter the infix expression: ";cin>>infix;
for(int i=0;infix[i]!='\0';i++)
{
convertToPostfix(infix[i]);
}
}
void ShowResult()
{
cout<<"Postfix expression"<<endl;
for(int j=0;postfix[j]!='\0';j++)
{
cout<<postfix[j];
}
}
void convertToPostfix(char c)
{
int p=0;
Stack myStack;
precedence=prec(c);
entry2=myStack.topShow();
if(isdigit(c))
{
postfix[++p]=c;
}
if(precedence>prec(entry2))
{
myStack.push(c);
}
if(precedence<prec(entry2))
{
switch(c)
{
case '(': myStack.push(c); break;
case ')': while(myStack.topShow()!= '(')
{
postfix[++p]=myStack.topShow();
myStack.pop();
};myStack.pop();break;
case '+':
case '-':
case '*':
case '/': while(prec(myStack.topShow())>=precedence)
{
postfix[++p]=myStack.topShow();
myStack.pop();
};break;
}
}
}
};
int main()
{
Expression myExp;
myExp.Read();
myExp.ShowResult();
return 0;
}
Here are some issues I found:
Boolean Functions Return true or false
Match return types with return values. The numbers 1 and 0 are not Boolean values.
Precedence table
Add and subtract have same precedence.
Multiply and divide have same precedence.
Multiply and divide have higher precedence than add and subtract.
Stack disappears
Since the stack is declared as a local variable in the function, it will be created fresh when entering the function and destroyed before exiting the function.
Solution: move it to the class as a class member or declare it as static.
Multiple statements per line are not more efficient
Blank lines and newlines do not affect performance, and add negligible time to the build.
However, they make your program more readable which helps when inspecting or debugging. Use them.
And similarly with space before and after operators.
Build the habit now rather than correcting when you get a job.
Call function once and store the value
You call prec(entry2) twice, which is a waste of time. Call it once and save the value in a variable. Similarly with stack.TopShow().
Use std::vector not an array
The std::vector will grow as necessary and reduce the chance of buffer overflow.
With an array, you must check that your indices are always within range. Also, array capacities don't change; you have to declare a new instance and copy the data over.
The variable mx is not declared
The compiler should catch this one. You use mx as the capacity for an array and comparing for full. However, it is never declared, defined nor initialized. Prefer std::vector and you won't have to deal with these issues.
Input is not validated
You input a letter, but don't validate it.
Try these characters: space, #, #, A, B, etc.
Missing default for switch
Crank up your compiler warnings to maximum.
Your switch statements need defaults.
What precedence do numeric characters ('0'..'9') have?
(You check the precedence of numeric characters.)
Check all paths through your functions and program.
Using a debugger (see below) or pen and paper, check your program flow through you functions. Include boundary values and values not within the bounds.
Case statements: break or return
You don't need a break after a return statement. Think about it. Can the program continue executing at the line after a return statement?
Use a debugger or print statements
You can print variables at different points in your program. This is an ancient technique when debuggers are not available.
Learn to use a debugger. Most IDEs come with them. You can single step each statement and print out variable values. Very, very, useful.
class infixToPostfix{
public static void postfix(String str){
Stack<Character> stk = new Stack<Character>();
for(Character c : str.toCharArray()){
// If operands appears just print it
if(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z'){
System.out.print(c);
}else{
// Open paranthesis push is
if(c == '('){
stk.push(c);
//Close paranthesis pop until close paranthesis
}else if( c == ')'){
while(stk.peek() != '(')
System.out.print(stk.pop());
stk.pop();
// check the precedence of operator with the top of stack
}else if(c == '+' || c == '-'){
if(!stk.isEmpty()){
char top = stk.peek();
if(top == '*' || top == '/' || top == '+' || top == '-'){
System.out.print(stk.pop());
}
}
stk.push(c);
}else{
if(!stk.isEmpty()){
char top = stk.peek();
if(top == '/' || top == '*'){
System.out.print(stk.pop());
}
}
stk.push(c);
}
}
}
//Print all the remaining operands
while(!stk.isEmpty()) System.out.print(stk.pop());
System.out.println();
}
public static void main(String args[]){
String str = "A+B-(c+d*Z+t)/e";
postfix(str);
}
}
using stack and map u can solve the problem
1) create a map having operator as key and some integer to set priority. operator with same precedence will have same value something like:
map<char,int>oprMap;
oprMap['^'] = 3;
oprMap['*'] = 2;
oprMap['/'] = 2;
oprMap['+'] = 1;
oprMap['-'] = 1;
2) iterate through given expression call these checks
1) if current element
i) is operand add it to result
ii) not operand do following check
a. while not (stack is empty and element is open bracket and found operator with higher precedence.
add top of the stack to the result and pop()
b. push current element to stack
iii) if open brackets push to stack
iv) if closed brackets pop until get closed bracket and add it to result
3) while stack is not empty pop() and add top element to the result.
{
stack<char>S;
for (int i = 0; i < n; i++) {
if(isOperand(exps[i])) {
res = res + exps[i];
} else if(isOperator(exps[i])){
while(!(S.empty() && isOpenParanthesis(S.top()) && isHeigherPrecedence(S.top(),exps[i])){
res = res+S.top();
S.pop();
}
S.push(exps[i]);
} else if(isOpenParanthesis(exps[i])) {
S.push(exps[i]);
} else if(isClosingParanthesis(exps[i])) {
while(!S.empty() && !isOpenParanthesis(S.top())) {
res = res+S.top();
S.pop();
}
S.pop();
}
}
while(!S.empty()) {
res = res + S.top();
S.pop();
}
}
}
#include<bits/stdc++.h>
using namespace std;
// This isHigher function checks the priority of character a over b.
bool isHigher(char a,char b)
{
if(a=='+' || a=='-')
return false;
else if((a=='*' && b=='*') || (a=='*' && b=='/') || (a=='/' && b=='*') ||
(a=='/' && b == '/')|| (a=='^' && b=='^')||(a=='*' && b=='^') || (a=='/' &&
b=='^'))
return false;
return true;
}
int main(){
string s;
cin>>s;
s = s + ")";
//Vector postfix contains the postfix expression.
vector<char>postfix;
stack<char>mid;
mid.push('(');
for(int i=0;i<s.length();i++)
{
if(s[i] == '(')
mid.push(s[i]);
else if(s[i] == '+' || s[i] == '^' || s[i] == '-' || s[i] == '*'||
s[i] == '/')
{
if(mid.top() == '(')
mid.push(s[i]);
else {
if(isHigher(s[i],mid.top()))
mid.push(s[i]);
else
{
while(mid.top()!='(')
{
if(!isHigher(s[i],mid.top()))
{
postfix.push_back(mid.top());
mid.pop();
}
else
break;
}
mid.push(s[i]);
}
}
}
else if(s[i] == ')')
{
while(mid.top() != '(')
{
postfix.push_back(mid.top());
mid.pop();
}
mid.pop();
}
else
postfix.push_back(s[i]);
}
for(int i=0;i<postfix.size();i++)
cout<<postfix[i];
return 0;
}

Checking union equality

struct Something {
union {
float k;
int n;
};
bool isFloat;
bool operator==(const Something& mS)
{
if(isFloat != mS.isFloat) return false;
if(isFloat && mS.k == k) return true;
if(!isFloat && mS.n == n) return true;
}
};
My implementation of Something::operator== seems rather expensive and convoluted. Is this the only way to check equality in classes with union types?
Or is there a better way that avoids branches/checking additional variables?
bool operator==(const Something& mS)
{
if (isFloat != mS.isFloat)
{
return false;
}
else if (isFloat)
{
return mS.k == k;
}
else
{
return mS.n == n;
}
}
Clear and debuggable with the minimum number of checks. You want to have a constructor and/or set methods to ensure isFloat is correct at all times.
You can remove one redundant check, and perhaps enhance readability slightly, by replacing the last two lines with
if(isFloat != mS.isFloat) return false; // As you have
return isFloat ? mS.k == k : mS.n == n;
(or the equivalent if construct, as in Sean Perry's answer) but the compiler will probably do just as good a job of optimising your version.
There's no way to avoid a runtime check that the types match. You might consider a ready-made discriminated union type like Boost.Variant; it won't be any more efficient, but it might be easier and less error-prone to use.
return (isFloat && mS.isFloat && k==mS.k) || (!isFloat && !mS.isFloat && n==mS.n);
I do not think that you can escape checking all the conditions. So the question can be how to write them more simpler and expressively.
I would write them the following way
bool operator==( const Something &mS ) const
{
return ( ( isFloat == mS.isFloat ) && ( isFloat ? k == mS.k : n == mS.n ) );
}

What is the best way to implement operator<?

Sorry if this is a stupid question, but it's something that I'm curious about.
I am overloading the less-than operator for my sort algorithm based on last name, first name, middle name. I realize there is not a right or wrong here, but I'm curious as to which style is written better or preferred among fellow programmers.
bool CPerson::operator<(const CPerson& key) const
{
if (m_Last < key.m_Last)
|| ( (m_Last == key.m_Last) && (m_First < key.m_First) )
|| ( (m_Last == key.m_Last) && (m_First == key.m_First) && (m_Middle < key.m_Middle) )
return true;
return false;
}
or
bool CPerson::operator<(const CPerson& key) const
{
if (m_Last < key.m_Last)
return true;
else if ( (m_Last == key.m_Last) && (m_First < key.m_First) )
return true;
else if ( (m_Last == key.m_Last) && (m_First == key.m_First) && (m_Middle < key.m_Middle) )
return true;
else
return false;
}
or
bool CPerson::operator<(const CPerson& key) const
{
if (m_Last < key.m_Last)
return true;
if (m_Last == key.m_Last)
if (m_First < key.m_First)
return true;
if (m_Last == key.m_Last)
if (m_First == key.m_First)
if (m_Middle < key.m_Middle)
return true;
return false;
}
I prefer:
bool CPerson::operator<(const CPerson& key) const
{
if (m_Last == key.m_Last) {
if (m_First == key.m_First) {
return m_Middle < key.m_Middle;
}
return m_First < key.m_First;
}
return m_Last < key.mLast;
}
Nice and systematic, and it is obvious how new members can be added.
Because these are strings, the repeated comparison may be needlessly inefficient. Following David Hamman's suggestion, here is a version which only does the comparisons once per string (at most):
bool CPerson::operator<(const CPerson& key) const
{
int last(m_Last.compare(key.m_Last));
if (last == 0) {
int first(m_First.compare(key.m_First));
if (first == 0) {
return m_Middle < key.m_Middle;
}
return first < 0;
}
return last < 0;
}
All of your implementations are essentially the same and they are all wrong by any reasonable definition of sort order for people's names. Your algorithm will place Jonathan Abbott Zyzzyk ahead of Jonathan Zuriel Aaron.
What you want is person A's name is less than person B's name if:
The last name of person A is less than the last name of person B or
The two have the same last name and
The first name of person A is less than the first name of person B or
The two have the same first name and the middle name of person A is less than the middle name of person B.
Whether you implement this as a single boolean expression versus a staged if/else sequence is a bit of personal preference. My preference is the single boolean expression; to me that logical expression is clearer than a cluttered if/else sequence. But apparently I'm weird. Most people prefer the if/else construct.
Edit, per request
As a single boolean expression,
bool Person::operator< (const Person& other) const {
return (last_name < other.last_name) ||
((last_name == other.last_name) &&
((first_name < other.first_name) ||
((first_name == other.first_name) &&
(middle_name < other.middle_name))));
}
I find the first one the most difficult to read of the three (although none of them are too difficult) and the first one has unnecessary parentheses. The second one is my personal preference, because the third one seems too long and verbose.
This really is subjective though.
I normally write a comparison function roughly like this:
bool whatever::operator<(whatever const &other) {
if (key1 < other.key1)
return true;
if (other.key1 < key1)
return false;
// compare the second key item because the first ones were equal.
if (key2 < other.key2)
return true;
if (other.key2 < key2)
return false;
// repeat for as many keys as needed
// for the last key item, we can skip the second comparison:
if (keyN < other.keyN)
return true;
return false; // other.keyN >= keyN.
}
Along a slightly different vein, all of the solutions (including my first answer) tend to compare names twice, once for less than and again for equality. Since sort is at best an N*logN algorithm, efficiency can be quite important when sorting a big list of names, and these duplicative comparisons are rather inefficient. The string::compare method provides a mechanism for bypassing this problem:
bool Person::operator< (const Person& other) const {
int cmp = last_name.compare (other.last_name);
if (cmp < 0) {
return true;
} else if (cmp == 0) {
cmp = first_name.compare (other.first_name);
if (cmp < 0) {
return true;
} else if (cmp == 0) {
cmp = middle_name.compare (other.middle_name);
if (cmp < 0) {
return true;
}
}
}
return false;
}
Edit, per request
Elided.
A boolean version of the above will either result in undefined behavior or will use multiple embedded uses of the ternary operator. It is ugly even given my penchant for hairy boolean expressions. Sorry, Mankarse.
I like to reduce this to tuples, which already implement this kind of lexicographical ordering. For example, if you have boost, you can write:
bool Person::operator< (const Person& Rhs) const
{
return boost::tie(m_Last, m_First, m_Middle) < boost::tie(Rhs.m_Last, Rhs.m_First, Rhs.m_Middle);
}

C++ "OR" operator

can this be done somehow?
if((a || b) == 0) return 1;
return 0;
so its like...if a OR b equals zero, then...but it is not working for me.
my real code is:
bool Circle2::contains(Line2 l) {
if((p1.distanceFrom(l.p1) || p1.distanceFrom(l.p2)) <= r) {
return 1;
}
return 0;
}
You need to write the full expression:
(a==0)||(b==0)
And in the second code:
if((p1.distanceFrom(l.p1)<= r) || (p1.distanceFrom(l.p2)<=r) )
return 1;
If you do ((a || b) == 0) this means "Is the logical or of a and b equal to 0. And that's not what you want here.
And as a side note: the if (BooleanExpression)return true; else return false pattern can be shortened to return BooleanExpression;
You have to specify the condition separately each time:
if (a == 0) || (b == 0))
bla bla;
When you do
if ((a || b) == 0)
bla bla;
it has a different meaning: (a || b) means "if either a or b is non-zero (ie. true), then the result of this expression is true".
So when you do (a||b) == 0, you are checking if the result of the previously explained expression is equal to zero (or false).
The C++ language specifies that the operands of || ("or") be boolean expressions.
If p1.distanceFrom(l.p1) is not boolean (that is, if distanceFrom returns int, or double, or some numeric class type), the compiler will attempt to convert it to boolean.
For built in numeric type, the conversion is: non-zero converts to true, zero converts to false. If the type of p1.distanceFrom(l.p1) is of class type Foo, the compiler will call one (and only one) user defined conversion, e.g., Foo::operator bool(), to convert the expression's value to bool.
I think you really want something like this:
bool Circle2::contains(Line2 l) {
if((p1.distanceFrom(l.p1) <= r) || (p1.distanceFrom(l.p2) <= r)) return 1;
return 0;
}
Fun with templates:
template <typename T>
struct or_t
{
or_t(const T& a, const T& b) : value1(a), value2(b)
{
}
bool operator==(const T& c)
{
return value1 == c || value2 == c;
}
private:
const T& value1;
const T& value2;
};
template <typename T>
or_t<T> or(const T& a, const T& b)
{
return or_t<T>(a, b);
}
In use:
int main(int argc, char** argv)
{
int a = 7;
int b = 9;
if (or(a, b) == 7)
{
}
return 0;
}
It performs the same comparison you would normally do, though, but at your convenience.
If you have lot of that code, you may consider a helping method:
bool distanceLE (Point p1, Point p2, double threshold) {
return (p1.distanceFrom (p2) <= threshold)
}
bool Circle2::contains (Line2 l) {
return distanceLE (p1, l.p1, r) && distanceLE (p1, l.p2, r);
}
If you sometimes have <, sometimes <=, >, >= and so on, maybe you should pass the operator too, in form of a function.
In some cases your intentions by writing this:
if ((a || b) == 0) return 1;
return 0;
could be expressed with an bitwise-or:
if ((a | b) == 0) return 1;
return 0;
and simplified to
return ! (a | b);
But read up on bitwise operations and test it carefully. I use them rarely and especially I didn't use C++ for some time.
Note, that you inverted the meaning between your examples 1 and 2, returning true and false in the opposite way.
And bitwise less-equal doesn't make any sense, of course. :)
C++ doesn't support any construct like that. Use if (a == 0 || b == 0).
Your condition should be (a == 0 || b == 0) or (p1.distanceFrom(l.p1) <= r || p1.distanceFrom(l.p2)) <= r)
C++ isn't that smart. You have to do each comparison manually.
bool Circle2::contains(Line2 l) {
if((p1.distanceFrom(l.p1) <= r) || (p1.distanceFrom(l.p2) <= r)) return 1;
return 0;
}