I came across the following for loop with a very unusual condition
int main( int argc, const char* argv[] ) {
for ( int i = 0 ; i < ( 10, 20 ) ; i++ ) {
cout << i << endl;
}
}
This source code compiled successfully. It executed the loop with i with values from 0 to 19 (the 10 in the expression (10, 20) seems to have no effect on the number of iterations).
My question:
What is this condition syntax? Why doesn't it cause a compile error?
EDIT:
The bigger picture: this questions started with a bug, the original condition was supposed to be i < std::min( <expr A>, <expr B> ) and for some reason I omitted the std::min.
So, I was wondering why the code compiled in the first place. Now I see the bug is a legit (albeit useless) syntax.
Thanks!
It is the comma operator. It evaluates both sides of the expression, and returns the right one.
So, expression (10, 20) does nothing, but returns '20'.
See also
Uses of C comma operator.
http://en.wikipedia.org/wiki/Comma_operator
(10, 20) means evaluate the integer 10, then evaluate 20, then return 20 (the rightmost). So it just means 20.
The comma operator is often useful in for loops, as it allows things such as x = 0, y = 1 (i.e. two assignments in one expression), but here it's useless.
, operator in c++ work as a binary operator which checks first value, discard it and return the next value. In short.
for(int i=0;i<(10,20);i++) will be equal to for(int i=0;i<20;i++)
Related
INTENTION -> A program that adds even numbers only within a range
Strange behavior -> the logical statement is incorrect for adding even numbers, instead the logical statement is correct for adding odd numbers, but the sum of even numbers is the result. As we all know, num & 1 returns true if num is odd, and false if num is even.
Question -> Check my logical statement in the code. Why is the increment of n inline with the logical operator inverting the return value and summing even numbers (which is intended, but unexpected for this logical statement)?
//program to print sum of even numbers
#include <iostream>
int main(){
int n = {0}, result = {0};
while(n < 99) result += n++ & 1 ? n : 0;
std::cout << result << '\n';
}
I was experiencing some random behavior when attempting a simple coding implementation of a bitwise odd number detection. num & 1
This is returning the desired and appropriate value of even nums between 0 and 100, when I'm not using any negation. such as ~num & 1 . Can someone explain to me why the negation isn't necessary, and why its returning even values? Is there some extra behavior to the n++ happening?
NOTE: I understand the syntax is obtuse, that was sort of my intention, to be as obtuse as possible for the sake of experimenting with the language a bit. I'm not asking for a style critique.
Examples
https://repl.it/KG8Z/1 < this should print odd, but what is the unintended side-effect of the ++ operator that is making it print even numbers?
https://repl.it/KG8Z/0 < c++
https://repl.it/KGId/3 < python
I was expecting to need to use the bitwise not operator in c++ to get the desired result, but the results are the same despite the absence of a logical not. How to explain this odd behavior?
When
n++ & 1
executes, lets expect n is odd number at the moment, condition is true.
Post incrementation is applied and n is even when
result += n
executes. Thats why its counting even numbers instead of odd. Modify code to
while(n < 99) result += !(n++ & 1) ? n : 0;
and it will count odd one's.
[expr.cond]/1:
Conditional expressions group right-to-left. The first expression is
contextually converted to bool. It is evaluated and if it is true, the
result of the conditional expression is the value of the second
expression, otherwise that of the third expression. Only one of the
second and third expressions is evaluated. Every value computation and
side effect associated with the first expression is sequenced before
every value computation and side effect associated with the second or
third expression.
Thus, n is "selected" on odd ns in the condition, but at that point, it's already incremented (even).
n & ~1 is not the same as !(n & 1).
How can I convert C code to C++? When I try my best, I failed every time.
Can anyone help me?
In particular, I'm trying to understand the following:
v=v%10?v%(5*r)*n--:v/10
I know if v == v mod 10,v%(5*r)*n--. if not, v/10. But I don't understand v%(5*r)*n--.
Here's the code in context:
long v=1,r=1e9;
main(n){
for(scanf("%d",&n);v=v%10?v%(5*r)*n--:v/10;n||printf("%d",v%r));
}
This C expression is also valid in C++. Expression v%(5*r)*n-- is equivalent to expression v % ((5*r)*(n--)) due to operator precedence rules. Postfix decrement operator --(it decreases a variable by one) will evaluate first, what remains is an expression of type A % B * C. Since operators % (remainder) and * (multiplication) are on the same precedence level, left to right associativity rule will be applied. Therefore, we have v % ((5*r)*(n--)). For more information check out these links:
http://en.cppreference.com/w/cpp/language/operator_precedence
https://en.wikipedia.org/wiki/Operator_associativity
You also do no understand the ternary operator. In your case, the whole statement v=v%10?v%(5*r)*n--:v/10 means: if v%10 is true (different from zero) then assign result of v%(5*r)*n-- to variable v, otherwise assign result of v/10 to variable v. For more information check out
http://www.cprogramming.com/reference/operators/ternary-operator.html
Btw, please note that the person writing this blog produces some awful code. You probably do not want to learn from it.
Your definition for main is bad. C++ does not allow implicit typing for functions1, and main takes either zero or two arguments; it should be written as
int main( int argc, char **argv )
{
...
}
if the program takes any command line arguments2 and
int main( void )
{
...
}
if it doesn't3.
The expression v=v%10?v%(5*r)*n--:v/10 is equally valid (if unspeakably ugly) in C and C++, so that's not an issue.
The expression n||printf("%d",v%r) is a bit of a head-scratcher, though; what do you think it's trying to accomplish?
Edit
Sorry, wasn't quite awake when I wrote that last bit. Obviously, the intent of that expression is to only write the value of v%r when n is 0.
The || is the logical-or operator - the expression a || b evaluates to 1 if either a or b is non-zero, or 0 if both a and b are zero. The operator short-circuits; if a is non-zero, then the result of a || b is 1 regardless of the value of b, so b won't be evaluated at all.
Thus, in the expression n || printf( "%d", v%r ), if n is non-zero, then the printf call won't be executed.
Note that the line
for(scanf("%d",&n);v=v%10?v%(5*r)*n--:v/10;n||printf("%d",v%r));
is hideous; even with some whitespace it would be hard to follow and debug. This should not be taken as an example of good code. That style of programming is only suitable for the IOCCC, except that it's not ugly enough for that particular competition.
A better way to write it for C++ would be
#include <iostream>
int main( void )
{
long v=1,r=1e9; // no reason to make these global
int n;
if ( std::cin >> n )
{
while ( v ) // v != 0
{
if ( v % 10 )
v = v % (5 * r) * n--; // whitespace is your friend, use it
else
v = v / 10;
if ( n ) // n != 0
std::cout << v % r;
}
}
else
{
std::cerr << "Error while reading \"n\"...try again" << std::endl;
}
return 0;
}
1. Neither does C since the 1999 standard, and it's bad practice anyway.
2. You don't have to use the names argc and argv, although they are the common convention.
3. Implementations may provide additional signatures for main (such as extra arguments in addition to argc and argv), but those additional signatures must be documented; don't assume any random signature is going to be valid.
while ( (i=t-i%10 ? i/10 : !printf("%d\n",j)) || (i=++j<0?-j:j)<101 );
I came across this on codegolf
Please explain the usage of ? and : and why is there no statement following the while loop? As in why is there a ; after the parenthesis.
There is a boolean operation going on inside the parentheses of the while loop:
while (boolean);
Since the ternary operator is a boolean operator, it's perfectly legal.
So what's this doing? Looks like modular arithmetic, printing going on over a range up to 101.
I'll agree that it's cryptic and obscure. It looks more like a code obfuscation runner up. But it appears to be compilable and runnable. Did you try it? What did it do?
The ?: is a ternary operator.
An expression of form <A> ? <B> : <C> evaluates to:
If <A> is true, then it evaluates to <B>
If <A> is false, then it evaluates to <C>
The ; after the while loop indicates an empty instruction. It is equivalent to writing
while (<condition>) {}
The code you posted seems like being obfuscated.
Please explain the usage of ? and :
That's the conditional operator. a ? b : c evaluates a and converts it to a boolean value. Then it evaluates b if its true, or c if its false, and the overall value of the expression is the result of evaluating b or c.
So the first sub-expression:
assigns t-i%10 to i. The result of that expression is the new value of i.
if i is not zero, the result of the expression is i/10
otherwise, print j, and the result of the expression is zero (since printf returns a non-zero count of characters printed, which ! converts to zero).
Then the second sub-expression, after ||, is only evaluated if the result of the first expression was zero. I'll leave you to figure out what that does.
why is there no statement following the while loop?
There's an empty statement, ;, so the loop body does nothing. All the action happens in the side effects of the conditional expression. This is a common technique when the purpose of the code is to baffle the reader; but please don't do this sort of thing when writing code that anyone you care about might need to maintain.
This is the Conditional Operator (also called ternary operator).
It is a one-line syntax to do the same as if (?) condition doA else (:) doB;
In your example:
(i=t-i%10 ? i/10 : !printf("%d\n",j)
Is equivalent to
if (i=t-i%10)
i/10;
else
!printf("%d\n",j);
?: is the short hand notation for if then else
(i=t-i%10 ? i/10 : !printf("%d\n",j)<br>
equals to
if( i= t-i%10 )
then { i/10 }
else { !printf("%d\n",j) }
Your while loop will run when the statement before the || is true OR the statement after the || is true.
notice that your code does not make any sense.
while ( (i=t-i%10 ? i/10 : !printf("%d\n",j)) || (i=++j<0?-j:j)<101 );
in the most human-readable i can do it for u, it's equivalent to:
while (i < 101)
{
i = (t - i) % 10;
if (i > 0)
{
i = i / 10;
}
else
{
printf("%d\n",j);
}
i = ++j;
if (i < 0)
{
i = i - j;
}
else
{
i = j;
}
}
Greetings.
I am the proud perpetrator of that code. Here goes the full version:
main()
{
int t=getchar()-48,i=100,j=-i;
while ((i=t-i%10?i/10:!printf("%d\n",j)) || (i=++j<0?-j:j)<101 );
}
It is my submission to a programming challenge or "code golf" where you are asked to create the tinniest program that would accept a digit as a parameter and print all the numbers in the range -100 to 100 that include the given digit. Using strings or regular expressions is forbidden.
Here's the link to the challenge.
The point is that it is doing all the work into a single statement that evaluates to a boolean. In fact, this is the result of merging two different while loops into a single one. It is equivalent to the following code:
main()
{
int i,t=getchar()-'0',j=-100;
do
{
i = j<0? -j : j;
do
{
if (t == i%10)
{
printf("%d\n",j);
break;
}
}
while(i/=10);
}
while (j++<100);
}
Now lets dissect that loop a little.
First, the initialisation.
int t=getchar()-48,i=100,j=-i;
A character will be read from the standard input. You are supposed to type a number between 0 and 9. 48 is the value for the zero character ('0'), so t will end up holding an integer between 0 and 9.
i and j will be 100 and -100. j will be run from -100 to 100 (inclusive) and i will always hold the absolute value of j.
Now the loop:
while ((i=t-i%10?i/10:!printf("%d\n",j)) || (i=++j<0?-j:j)<101 );
Let's read it as
while ( A || B ) /* do nothing */ ;
with A equals to (i=t-i%10?i/10:!printf("%d\n",j)) and B equals to (i=++j<0?-j:j)<101
The point is that A is evaluated as a boolean. If true, B won't be evaluated at all and the loop will execute again. If false, B will be evaluated and in turn, if B is true we'll repeat again and once B is false, the loop will be exited.
So A is the inner loop and B the outer loop. Let's dissect them
(i=t-i%10?i/10:!printf("%d\n",j))
It's a ternary operator in the form i = CONDITION? X : Y; It means that first CONDITION will be evaluated. If true, i will be set to the value of X; otherwise i will be set to Y.
Here CONDITION (t-i%10) can be read as t - (i%10). This will evaluate to true if i modulo 10 is different than t, and false if i%10 and t are the same value.
If different, it's equivalent to i = i / 10;
If same, the operation will be i = !printf("%d\n",j)
If you think about it hard enough, you'll see that it's just a loop that checks if any of the decimal digits in the integer in i is equal to t.
The loop will keep going until exhausting all digits of i (i/10 will be zero) or the printf statement is run. Printf returns the number of digits printed, which should always be more than zero, so !printf(...) shall always evaluate to false, also terminating the loop.
Now for the B part (outer loop), it will just increment j until it reaches 101, and set i to the absolute value of j in the way.
Hope I made any sense.
Yes, I found this thread by searching for my code in google because I couldn't find the challenge post.
char i;
for (i = 1; i < 10, i++;)
{
cout << (i+1) << endl;
}
return 0;
I understand that for loop has the following syntax:
for(initialization; condition; increment)
{
}
As I run the debug, why it never checks the condition and it eventually stops at i = 0?
(Thank you Damien and Andars, I don't know why the "on purpose" statement was removed, but you interpret my question correctly. Could someone explain why the complier skips the condition before the comma, and why the loop stop at i = 0 instead of looping forever? Thanks!)
I believe he is indicating that he wrote the code that way on purpose.
To answer, i++ will always return true. The last value is the value that matters with comma separated statements, so the loop will not stop.
Edit for elaborations:
It isn't simply using a logical or, it disregards what is before the comma and only takes the last value. The value of anything non-zero is considered true, and since i starts at 1, and goes up, it will always be non-zero (until it overflows and wraps back around, which explains why i ends at 0).
If you say:
x = 4, 5, 6;
x will be equal to 6, the last value.
Change
for (i = 1; i < 10, i++;)
to
for (i = 1; i < 10; i++)
Change to
for (i = 1; i < 10; i++) //Notice correct placement of ;
It seems to me also that the code was written incorrectly on purpose. As others have mentioned, the comma operator will discard the value of the i<10 and only i++ will be evaluated as condition. This will return true until i overflows (values only from -127 to 127) and ends up at -1, when i++ will return 0 and the loop exits. Thus the final value for i will be 0.
Because you used the comma operator instead of a semi-colon
I've noticed on a number of occasions when refactoring various pieces of C and C++ code that a comma is used rather than a semi-colon to seperate statements. Something like this;
int a = 0, b = 0;
a = 5, b = 5;
Where I would have expected
int a = 0, b = 0;
a = 5; b = 5;
I know that C and C++ allow use of commas to seperate statements (notably loop headers), but what is the difference if any between these two pieces of code? My guess is that the comma has been left in as the result of cut & pasting, but is it a bug and does it effect execution?
It doesn't make a difference in the code you posted. In general, the comma separates expressions just like a semicolon, however, if you take the whole as an expression, then the comma operator means that the expression evaluates to the last argument.
Here's an example:
b = (3, 5);
Will evaluate 3, then 5 and assign the latter to b. So b = 5. Note that the brackets are important here:
b = 3, 5;
Will evaluate b = 3, then 5 and the result of the whole expression is 5, nevertheless b == 3.
The comma operator is especially helpful in for-loops when your iterator code is not a simple i++, but you need to do multiple commands. In that case a semicolon doesn't work well with the for-loop syntax.
The comma is a operator that returns a value which is always the 2nd (right) argument while a semicolon just ends statements. That allows the comma operator to be used inside other statements or to concatenate multiple statements to appear as one.
Here the function f(x) gets called and then x > y is evaluated for the if statement.
if( y = f(x), x > y )
An example when it's used just to avoid a the need for block
if( ... )
x = 2, y = 3;
if( ... ) {
x = 2;
y = 3;
}
The comma operator evaluates all operands from left to right, and the result is the value of the last operand.
It is mostly useful in for-loops if you want to do multiple actions in the "increment" part, e.g (reversing a string)
for (int lower = 0, upper = s.size() - 1; lower < upper; ++lower, --upper)
std::swap(s[lower], s[upper]);
Another example, where it might be an option (finding all occurrences in a string):
#include <string>
#include <iostream>
int main()
{
std::string s("abracadabra");
size_t search_position = 0;
size_t position = 0;
while (position = s.find('a', search_position), position != std::string::npos) {
std::cout << position << '\n';
search_position = position + 1;
}
}
In particular, logical and cannot be used for this condition, since both zero and non-zero can mean that the character was found in the string. With comma, on the other hand, position = s.find() is called each time when the condition is evaluated, but the result of this part of the condition is just ignored.
Naturally there are other ways to write the loop:
while ((position = s.find('a', search_position)) != std::string::npos)
or just
while (true) {
position = s.find('a', search_position);
if (position == std::string::npos)
break;
...
}
As Frank mentioned, how the comma operator is used in your example doesn't cause a bug. The comma operator can be confusing for several reasons:
it's not seen too often because it's only necessary in some special situations
there are several other syntactic uses of the comma that may look like a comma operator - but they aren't (the commas used to separate function parameters/arguments, the commas used to separate variable declarations or initializers)
Since it's confusing and often unnecessary, the comma operator should be avoided except for some very specific situations:
it can be useful to perform multiple operation in one or more of a for statement's controlling expressions
it can be used in preprocessor macros to evaluate more than one expression in a single statement. This is usually done to allow a macros to do more than one thing and still be a a single expression so the macro will 'fit' in places that only allow an expression.
The comma operator is a hackish operator pretty much by definition - it's to hack in 2 things where only one is allowed. It's almost always ugly, but sometimes that's all you've got. And that's the only time you should use it - if you have another option, don't use the comma operator.
Off the top of my head I can't think of too many other reasons to use the operator, since you can get a similar effect by evaluating the expressions in separate statements in most other situations (though I'm sure that someone will comment on a another use that I've overlooked).
One usage would be in code golfing:
if (x == 1) y = 2, z = 3;
if (x == 1) { y = 2; z = 3; }
The first line is shorter, but that looks too confusing to use in regular development.