Given the following code:
// this is a solution of uva 12279
#include<stdio.h>
int main()
{
int arr[10000],i,n,a,d=0,e=75;
while(scanf("%d",&n),n)// what's that means?
{
d++;
int c=0,b=0;
if(n==0)
return 0;
for(i=0;i<n;i++)
scanf("%d",&arr[i]);
for(i=0;i<n;i++)//this is for loop
{
if(arr[i]==0)
c++;
else
b++;
}
a=b-c;
printf("Case %d: %d\n",d,a);
}
return 0;
}
What is the meaning of while(scanf("%d",&n),n)?
In this condition
while(scanf("%d",&n),n)
there is used the so-called comma operator.
scanf("%d",&n),n
The value of the condition is the value of the second operand of the comma operator that is of the variable n. If n is not equal to 0 then the loop is executed.
You can imagine it the following way
start: scanf("%d",&n);
if ( n != 0 )
{
//...
goto start;
}
Thus within the body of the loop the variable n can not be equal to 0 unless it is reassigned. As result this statement from the presented code snippet
if(n==0)
return 0;
does not make sense.
It would be more correct to write the condition of the loop the following way
while ( scanf("%d",&n) == 1 && n != 0 )
From the C Standard (6.5.17 Comma operator)
2 The left operand of a comma operator is evaluated as a void
expression; there is a sequence point between its evaluation and that
of the right operand. Then the right operand is evaluated; the result
has its type and value.
Related
int get_fact(int N)
{
int fact=1;
while(N--)
{
fact=fact*N;
}
return fact;
}
Why it is giving ans zero??
Tried to have the factorial of N.
here while loop used.but somehow 0 is multiplicatd. But why this happened?
A while loop let you do repeated execution of code until the Boolean value becomes false(when the condition becomes 0).
This line
while (N--)
will continue executing until the value of N equals 0, at which point the condition becomes false. Any number multiplied by 0 results in 0.
There's your answer.
Change that to:
int get_fact(int N)
{
int fact = 1;
while(N)
{
fact = fact * N;
N--;
}
return fact;
}
On the difference between prefix and postfix ++ in C, see also;
https://www.eskimo.com/~scs/readings/autoincrement.990118.html
In this scenario, why is it that the output for i is 1 and not 0, since the while loop decrements the value for i two times from it's original value i=2?
#include<stdio.h>
int main(){
int i=2,j=2;
while(i+1?--i:j++)
printf("%d",i);
return 0;
}
It is because your complicated ternary operator can be reduced to
while(--i)
Explanation.
i+1 == 3, --i executes. i == 1 so the body of while loop executes (prints 1). now i+1 == 2, --i executes, i == 0 which is false in C and body of the while loop is being skipped.
i is decremneted twice - but printf executed only 1 time.
You can test it adding one more printf:
int main(){
int i=2,j=2;
while(i+1?--i:j++)
printf("%d\n",i);
printf("%d\n",i);
return 0;
}
and the result will be as expected
1
0
Explanation:
I've following problem statement at hand, I came across an interesting 2 liner, C solution for it under leedcode discussion section. I tried to decompose it to understand what it means, and except one small line, I understood the rest. My question is at the end.
Leetcode Problem Statement:
Given an array arr of positive integers sorted in a strictly increasing order, and an integer k.
Find the kth positive integer that is missing from this array.
Example 1: Input: arr = [2,3,4,7,11], k = 5
Output: 9
Explanation: The missing positive integers are
[1,5,6,8,9,10,12,13,...]. The 5th missing >>positive integer is 9.
Example 2:
Input: arr = [1,2,3,4], k = 2
Output: 6
Explanation: The missing positive integers are [5,6,7,...].
The 2nd missing positive integer is 6.
Constraints:
1 <= arr.length <= 1000
1 <= arr[i] <= 1000
1 <= k <= 1000
arr[i] < arr[j] for 1 <= i < j <= arr.length
Two liner C solution:
int findKthPositive(int* arr, int arrSize, int k){
for (int arrCurrIndex = 0, counter = 1 ; (k && (arrCurrIndex < arrSize) ? ((arr[arrCurrIndex] != counter) ? k-- : ++arrCurrIndex) : k--) || (k = counter-1, 0) ; counter++);
return k;
}
For reference: Following is a similar algorithm that's being deployed, but its just cleaner to understand.
int findKthPositive(int* arr, int arrSize, int k){
for (int counter=1, arrCurrIndex=0; counter<10000; counter++) {
// exceed arr limits
if (arrCurrIndex < arrSize) {
if (counter == arr[arrCurrIndex]) { // found element in array
index++;
continue;
}
}
// missing element
k--;
if (k==0) {
return counter;
}
}
return 0;
}
My question:
What does following line in solution #1 means exactly?
(k = counter-1, 0)
======UPDATE ON ANSWER=======
I modified solution #1 in question slightly to make it more readable. It highlights what is going on with the given statement in question.
Here is the modified solution:
int findKthPositive(int* arr, int arrSize, int k){
// move counter out of the foor loop
int counter=1;
for (int arrCurrIndex = 0;
(k && (arrCurrIndex < arrSize) ?
((arr[arrCurrIndex] != counter) ? k-- : ++arrCurrIndex)
: k--); counter++);
return counter-1;
}
The binary comma operator , evaluates the first operand, discards the result and then evaluates the second one.
In the expression you posted we have
... || (k = counter-1, 0) ;
so counter-1 is actually assigned to k but its evaluation (k itself) is discarded so that 0 is used. Why 0? Because it is the neutral operand for logic or operator ||. In fact
X || 0 ==> X
In other words we have the expression
stuff_at_the_left || (k = counter-1, 0 )
that is evaluated as
stuff_at_the_left || 0
And since 0 is the neutral operand in logical or, the final evaluation is stuff_at_the_left.
The purpose of this weird expression is to cheat: the author at some point needed to assign that value to k but without adding more lines "ruining" the one liner. So they included the assignment in the logical expression making it neutral with comma operator combined with or operator's neutral operand.We also have to say that the assignment k=counter-1, 0 is performed only if all stuff_at_the_left is evaluated as 0 (due to the short circuiting nature of logical operators in C). The resulting expanded code is
if (!stuff_at_the_left)
k= counter-1;
Note: the comma operator has the lowest precedence among all the operators in C, and that's why the assignment is performed at first.
for (count = index, packet_no = 0;
count < TOTAL_OBJ, packet_no < TOTAL_PKT;
count++, packet_no++)
=> left-hand operand of comma expression has no effect.
I find the above code is correct and could not understand why this error comes.
This is how the comma operator works, what you want to do is to use OR or AND (probably AND in your case):
// the condition for resuming the loop is that one of the conditions is true
count < TOTAL_OBJ || packet_no < TOTAL_PKT
// the condition for resuming the loop is that both conditions are true
count < TOTAL_OBJ && packet_no < TOTAL_PKT
You have three comma operators in each of the three terms of the for statement. The warning is for term 2.
Both expressions of terms 1 and 3 are executed as expected.
The left operation of the term 2 is evaluated only as a void, doesn't take part in the for condition, and therefore leads to your warning.
The conditional statement(for, while or if ) having conditional expressions with comma operator(s), the value of last expression is the conditional value(True or False) of conditional statement.
For ex.
int i = 1;
int j = 0;
int k = 1;
if(i, j, k) {
printf("Inside");
}else {
printf("Outside");
}
prints "Outside" as comma operator is evaluated from left to right and k is the last expression evaluated in if statement which returns false.
int i, j;
if(i = 0 , j = 1) {
printf("Inside");
}else {
printf("Outside");
}
Above prints "Inside". j = 1 is the last expression evaluated inside the if statement which has true value.
int i = 1;
int j = 0;
int k = 1;
if(i, j, k) {
printf("Inside");
}else {
printf("Outside");
}
Correction to above: This code will print "Inside" as the comma operator is evaluated from left to right and k is the last expression evaluated in the if statement, which returns true since k = 1.
I had the following code in a test.I am confused about what (i,j) evaluates,while reading about the "," operator i found that it just evaluates the variables or functions but what does it do here?
main()
{
int i = 10, j = 20;
j = i ? (i, j) ? i : j : j;
printf("%d %d", i, j);
}
(i,j) is exactly the same as just j, because i is just a variable and evaluating it doesn't cause any side effect.
So basically it's just obfuscation here.
in (i,j), the , operator does nothing because the left-hand side expression does not have side-effects.
The assignment is thus equivalent to:
j = i? (j? i : j) : j;
And since i and j are non-zero, to j = i;
The comma operator can be used to link the related expressions together. A comma-linked list of expressions is evaluated left-to-right and the value of the rightmost expression is the value of the combined expression. It acts as a sequence point.
A sequence point guarantees that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.
So, any expression/assignment will be completed & only then will the next expression to the right be evaluated.
For example,
b=(a=4,a=5);
gives,
a=5
b=5
Also, note that the comma operator ranks last in the precedence list of operators in C.
It will print:
10 10
This is because you can break the expression down like:
j = i ? ((i, j) ? i : j) : j;
The comma operator evaluates to the last expression - so (i, j) == j. That is non-zero, so the center expression evaluates to i. 'i' being non-zero, the outer expression evaluates to i, so j is assigned to the value of i.
This is equivalent to:
int main() {
int i = 10, j = 20;
if (i != 0) {
(void)i; // Do nothing with i.
if (j != 0) {
j = i;
} else {
j = j; // Assign j to itself.
}
} else {
j = j; // Assign j to itself.
}
printf("%d %d", j);
}
Looks like typical software written test question. It is used to confuse candidates. As suggested by sepp2k above it is same as j. One more interview question
i = 10; j = 20;
1) k = i,j;
2) k = (i,j);
Answer for 1 will be 10 and answer for 2 will be 20. As coma operator doesnt do anything. I hope this will clear more.
It's not really doing anyting. It's evaluating the expression i, discards the result, evaluates the expression j and returns the result.
As evaluating the expression i has no side effects, (i,j) has the same meaning as just j.
main()
{
int i = 10, j = 20; // i=10, j=20
j = i ? /*if i */ ( (i, j) ? /* if j (1) */ i : /* else */ j ) : /* else */ j; // Added parenthesis and see (2)
printf("%d %d", i, j); // Will therefore print 10 10
}
it is equivallent to if(j) because (i,j) evaluate to j because i has no side effect.
all ifs evaluate to true because i and j are ints and are non zero