Here is a snippet of a pseudocode from a friend.
int a=50, b=20, c=10;
if (b=(b>a ? a:c))
c = a - b;
What does the code b>a ? a:c mean exactly?
It's called a conditional or ternary Operator.
It's similar to an if-else statement (short hand if Else). For example, here b>a ? a : c if b > a then it returns a else it returns c.
For more info just google it.
Related
I have implemented shunting-yard algorithm to parse arithmetic string-expressions from infix to postfix-notation.
I now also want to parse expressions with relational operators and Ternary conditional. Considering C++ Operator Precedence i added those operators with the lowest precedence and right-associativity for ? and : and the second-lowest and left-associativity for > and <.
When i now parse an expression like: A>B?C:D (where A, B, C and D can be any valid arithmetic expression) i would expect: A B > C D : ?, but i get A B C D : ? <. When i use Parentheses to evaluate the Condition first (A>B)?C:D it works. A mixed expression like (1+2<3+4)?C:D gives me 1 2 + 3 4 + < C D : ? which seems also legit to me. (A<B)?5+6:C gives me A B < 5 6 : + ? which again is messed up. Again, (A<B)?(5+6):C would fix that.
As stated in the comments, evaluating conditions first and the proceed with the left arithmetic expression would also be fine. But i really did not stumble upon an algorithm for evaluating expressions with relational and ternary operators in my research yet. Any help, even if pointing out an algorithm would be very appreciated
Here is the implementation of shunting-yard:
QQueue<QString> ShuntingYard::infixToPostfixWithConditionals(const QString& expression)
{
QStack<QString> stack;
QQueue<QString> queue;
QString token;
QStringList tokens = splitExpression(expression);
Q_FOREACH(QString token, tokens)
{
if (isDefineOrNumber(token))
queue.enqueue(token);
if (isFunction(token))
stack.push(token);
if (isOperator(token))
{
while (!stack.isEmpty() && isOperator(stack.top()) && isLeftAssociativeOperator(token) && !hasHigherPrecedence(token, stack.top()))
queue.enqueue(stack.pop());
stack.push(token);
}
if (isLeftParenthese(token))
stack.push(token);
else if (isRightParenthese(token))
{
while (!isLeftParenthese(stack.top()))
{
if (stack.isEmpty())
break;
if (isOperator(stack.top()))
queue.enqueue(stack.pop());
}
stack.pop();
if (isFunction(stack.top()))
queue.enqueue(stack.pop());
}
}
while (!stack.isEmpty())
{
if (isLeftParenthese(stack.top()))
break;
queue.enqueue(stack.pop());
}
return queue;
}
EDIT: made code and description more concise for readabilility
Another EDIT: Treating ?: as left-associative gave me the expected output
Now, regarding this question about the associativity of ternary conditionals. If i input a<b?a:b?c:d i get a b < a b c d : ? : ?, where a < b will be evaluated first, which is correct, due to its higher precedence, but then b ? c : d will be evaluated first, which is the correct right-to-left order. Confusing.
I've been familiar with the ternary operator for quite some time now, and have worked with it in a few differnet languages. My understanding of the operator is this:
condition ? expr1 : expr2
However, in C++, the following code is legal:
int i = 45;
(i > 0) ? i-- : 1;
Aren't you, in effect, just writing 1; or i - 1;How is this a complete statement? I understand that the intention of the code is to decrement i if it's greater than 0, but I would've thought that the code would generate a compiler error as just being an expression, not a full statement. I expected code like this:
int i = 45;
i = (i > 0) ? i - 1 : i;
This is called expression statement. The expression is evaluated and its value is discarded.
Even this is valid:
42;
although it does nothing. Only side effects (like i--, assignment, etc) in the expression have effects.
In fact, many statements we use are expression statements: assignments, function calls, etc:
a = 42;
foo();
That is a valid expression. You might have received a warning because you are not saving the result of the expression, but that you have the i-- your statement does have an effect.
In C++, an expression like 1 is a perfectly valid statement with no side effects. You could very feasibly write this function:
void f() {
1;
}
In fact, even this is correct.
void f() {
;;;;
}
A literal statement evaluates its arguments but does nothing more. The system views 1; as being just like func();. The only difference is that while func(); would logically have some side effects, 1; does not so it ends up being a no-op. The ternary operator evaluates like an if-statement, so the second form is only evaluated if the operand is true. Thus:
(i > 0) ? i-- : 1;
If i is greater than 0, the second form is evaluated. When it is evaluated, it carries its side effect, which decrements i by 1. Otherwise, the third form is evaluated, which does nothing. Although this block of code works, it is not incredibly readable, so while it's nice toy code a real if-statement is ideal for situations like this. For the same reason, this line would have the same effect but be frowned upon for being equally unreadable.
((i > 0) && (i--)) || 1;
Assuming you didn't overwrite the boolean operators, this code will short-circuit and behave like the ternary operator. If i is not greater than 0, then the && need not evaluate its second operand since the && is false, but the || must since it might be true. Inversely, if i is greater than 0, the && needs to evaluate but the || already knows it's true.
Aren't you, in effect, just writing 1; or i - 1;
No: i-- is not the same as i - 1. In the first case, the value of i is modified. In the second case it is not.
In the event that i less than or equal to zero, then you're correct that the resulting 'code' will be 1. However, the compiler will realise that this is not a useful thing to execute and so it ought to generate code equivalent to:
if( i > 0 ) i--;
Some (including myself) would consider that using the ternary operator in this fashion is bad style. Just for fun, here's another way someone might write it that's also not very nice (also more likely to generate compiler warning):
i > 0 && i--;
In the end, style is a matter of preference. The compiler, for the most part, will decide the best way to turn your code into assembly. So you owe it to yourself to write code that is clear and concise.
(Follow-up of Overload ternary ?: operator, or change to if{}else{} in included files.)
Context
Research project here. In my C++ library, I am including C files using #include "aprogram.c" which I execute symbolically by overloading (almost) all operators.
I have to be able to detect (condition) ? this : that and extract condition, this and that for usage in my symbolic execution library, for the following cases:
(a >= 0) ? a : -a
(a >= b) ? a : b
Conceptual question
Because I cannot overload the ternary ?: operator in C++, and it only has to work for the above cases, can't I 'overload' them by using macros somewhat like:
#define TO_NEG(a) ((a >= 0) ? a : -a)
#define MAX(a,b) ((a >= b) ? a : b)
and implement TO_NEG(a) and MAX(a,b)?
Edit: Clarification
With this, I want to achieve that my library
detects ?: in both cases
converts it to TO_NEG or MAX
uses new code I wrote for TO_NEG and MAX
Assuming your operator >= produces a MyBool type, I think you can get almost there with:
#define ? .ternary(
#define : )||
template <typename T>
T MyBool::ternary(T val) {
if (m_isTrue) return val;
return T(0)
}
Several things to note:
This doesn't work for a>=b if a is 0 and b is negative.
This is a terrible terrible hack that will break on many edge cases.
You can't actually use : as a symbol in a #define, so you'd have to use some other means of replacing them, at which point, you should probably use something like #raxvan's answer
You can define something that will replace the ? operator inside the c source file.
The closest thing you can do is the following:
#define QUESTION_OPERATOR(COND,THIS,THAT) ((COND) ? (THIS) : (THAT))
//here you can do custom validations to all the parts if you want
usage:
(cond) ? (This) : (That) //you need to replace this with:
QUESTION_OPERATOR(cond,This,That)
Yes, you can use the ternary operator in macros, but they must be correctly parenthesized:
#define TO_NEG(a) (a >= 0) ? (a) : -(a)
#define MAX(a,b) (a >= b) ? (a) : (b)
I have define the following macro,
#define abss(a) a >= 0 ? a : -a
while invoking this with,
int b=-1;
int c = abss(b);
printf("%d\n",c);
it should replaced in the form b >= 0 ? b : --b, which should output -2, but it outputs in my Bloodshed/DevC++ compiler 1.
I am analyzing C language for examination purpose, so I have to know what actually happens to the above case in C. Is the output result 1 is for CPP compiler I am using or what???
Your code
int b=-1;
int c = abss(b);
printf("%d\n",c);
gets translated by the preprocessor to:
int b=-1;
int c = b >= 0 ? b : -b;
printf("%d\n",c);
(the int b=-1 is in the C domain whereas the abss(b) gets expanded by the preprocessor before the compiler gets to int b=-1)
Why on earth do you think it should output -2?
#define abss(a) a >= 0 ? a : -a
so this:
int c = abss(b)
becomes
int c = b >= 0 ? b : -b
and b is -1, so that will evaluate to 1
by the way, you should bracket every use of a macro parameter, as you may get passed such things as x + 1. which would evaluate rather strangely.
Not to mention the results of abss(++x)
Your macro expands to
b >= 0 ? b : -b;
Not to b >= 0 ? b : --(-b); or whatever it is you expected.
Are you suggesting that
int x = -4;
-x;
should decrement x?
Bottom line - avoid macro use when possible.
The macro processor will never attach two adjacent tokens together, even if there is no whitespace between them, so indeed, as other posters have mentioned, your macro expands to - b, or 1.
If you want two tokens to become one when expanded by the preprocessor, you have to use the token pasting operator ##, something like
#define abss(a) a >= 0 ? a : - ## a
this will indeed do what you want, in the sense that the negative sign and the variable will form one token. Unfortunately (or fortunately, depending on how you look at it!) the pasted token "-b" will be invalid, and the expansion will not compile.
#define neg(a) -a
int b = -1;
neg(b);
In the above case, the macro is expanded to -b by the preprocessor, which will result in the value of 1. The preprocessor won't even be aware that the sign of the content of b is negative, so where should the second - come from to form a prefix decrement operator?
Even if you wrote it like this:
neg( -b );
Macro replacement is done on token level, not as a textual search & replace. You would get the equivalent of - ( -b ), but not --b.
Edit: The manual you link to in other comments is outdated (does not even address the C99 standard), and is dangerously bad. Just skimming through it I found half a dozen of statements that will make you look real stupid if you assume them to be correct. Don't use it, other than to light a fire.
This macro
#define abss(a) a >= 0 ? a : -a
is indeed hazardous, but the hazards are not where you think they are. The expression from your post
int c = abss(b);
works perfectly fine. However, consider what happens when the expression is not a simple variable, but is a function that is hard to calculate, or when it is an expression with side effects. For example
int c = abss(long_calc(arg1, arg2));
or
int c = abss(ask_user("Enter a value"));
or
int c = abss(b++);
If abss were a function, all three invocations would produce good results in predictable time. However, the macro makes the first call invoke long_calc and ask_user twice (what if the user enters a different number when prompted again?), and it post-increments b twice.
Moreover, consider this seemingly simple expression:
int c = abss(b) + 123;
Since + has a higher precedence than ? :, the resulting expansion will look like this:
int c = b >= 0 ? b : -b + 123;
When b is positive, 123 will not be added, so the meaning of the expression will change dramatically!
This last shortcoming can be addressed by enclosing the expression in parentheses. You should also enclose in parentheses each macro argument, like this:
#define abss(a) ((a) >= 0 ? (a) : -(a))
The reason for you getting the behaviour is preprocessor will just replace a with b and so effectively your code after preprocessing will be like
b >= 0 ? b : -b
and not
b >= 0 ? b : --b
So, when if b = -1, then it will effectively be considered as -(-1) and thus becomes 1.
You can check the preprocessor output and see it for yourself.
I once seen a -wired- operator in C++ which assigns value if greater than..
it was a combination of ?, < and =
e.g. let x = value if value is greater than x
I do not mean x=(x<value)x:value
It was some sort of x<?=value
But I can not remember it exactly, and can not find it online... Can some one remind me of it?
Thanks,
There is no operator that assigns variables based on their relative values.
However, there is the ?: operator:
x = value > x ? value : x;
If you read it out loud from left to right, it makes sense.
gcc has -- in version 3.3.6 at least! -- a gcc-specific language extension providing specialized operators for implementing min and max. Perhaps this is what you are thinking of?
Minimum and Maximum Operators in C++
I don't have gcc handy to test it with, but it might have an updating form, too.
How's that:
(x<value) || (x=value)
Are you thinking of the ternary operator?
result = a > b ? x : y;
I suspect what you're thinking of is a gcc extension1 that lets you leave out the middle operand to the conditional operator, so (for example):
a = b ? b : c;
can be written as:
a = b ?: c;
1 Despite the '2.95.3' in the URL, I'm not aware of a newer version of the linked page. If somebody is, please feel free to point it out (or edit it in).
it's a more convenient version of an if statement that is used for assignment
int x = (some bool) ? trueval : falseval;
this is roughly what it means, when the bool is evaluated it either gets the trueval or falseval depending on the outcome, it's easier than saying
int x;
if (someval)
x = trueval;
else
x = falseval;
x = x < value ? 0 : 1;
This function sets x to 0 is x < value, 1 otherwise.