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.
Related
I am unable to understand why this code is displaying 20 30 40 as output. Can anyone explain how the relational expression written in if statement is understood by the C Compiler ?
This is the image of code of the C Program
#include <stdio.h>
int main()
{
int i = 20, j = 30, k = 40;
if (i > j == k)
{
printf("%d %d %d ",--i,j++,++k);
}
else
{
printf("%d %d %d ",i,j,k );
}
return 0;
}
Output:
20 30 40
first thing to consider is operator precedence. the operator > is evaluated before the operator == and it returns a value. in this case, i > j is wrong so it returns zero. then it checks if zero equals to k which is 40 and it isn't. so it goes to else branch.
According operator precedence i > j == k is executed as (i > j) == k
So i > j is executed first, returning a boolean (here, false, ie 0)
And result is compared to k, which is not equal to 0. Condition is than false, so else part of condition is executed
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.
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.
The following code runs without giving any errors or warnings:
#include <stdio.h>
int main(){
int i, j;
int p = 0, q = 2;
for(i = 0, j = 0; i < p, j < q; i++, j++){
printf("Hello, World!\n");
}
return 0;
}
However, the book Let Us C (Yashwant Kanetkar) says that only one expression is allowed in the test expression of a for loop (see page 115 of the book).
I am not sure of the standard. Are multiple expressions allowed in the test expression of a for loop?
I surely can join the two expressions, but I was dumbstruck when I found the above code on this website. Is this valid C code or not?
The condition
i < p, j < q
is allowed but probably isn't what was intended as it discards the result of the first expression and returns the result of j < q only. The comma operator evaluates the expression on the left of the comma, discards it then evaluates the expression on the right and returns it.
If you want to test for multiple conditions use the logical AND operator && instead
i < p && j < q
You can link them together with boolean and (&&)
for(i = 0, j = 0; (i < p) && (j < q); i++, j++){
The above won't print out anything in the loop because the (i < p) condition fails immediately as i & p are both the same value (0).
Update: Your example is valid (but silly) C because if you start i=30 your loop will still execute 2 times, because the first result in a comma separated list is ignored.
If you want to test both conditions, use the && operator.
What is happening in your code is related to how the comma operator , works.
Both i < p and j < q are evaluated, but only the result of the 2nd expression j < q is checked by the for loop.
for(i = 0, j = 0; i < p && j < q; i++, j++){
Even I have read That Book by Mr Yashwant Kanetkar. It do says that only one condition is allowed in a for loop, however you can add multiple conditions in for loop by using logical operators to connect them. In other books that I have Read Along time Ago, said that only one condition is allowed.
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