Conditional expression in ternary operator in C - c

Code
#include <stdio.h>
int main() {
int i;
for (i=1; i<=10; i++) {
(i % 2) ? printf("%d is odd\n", i) : printf("%d is even\n", i);
}
}
Result
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
10 is even
In the above C program, why it still works fine even though the conditional expression only states i%2 and not i%2!=0 ?

In C, integers can be used in a Boolean context, and zero represents false while non-zero represents true.
That's why your code works. The expression num % 2 will be 0 (the single false value) for an even number and 1 (one of the many possible true values) for an odd number.
The following expressions would all work for detecting an odd number:
num % 2
(num % 2) != 0
((num % 2) != 0) != 0
... and so on, ad untilyougetboredum (like 'ad infinitum' but with limits).
Having said that, I don't really consider it a good idea to do it this way, code should express intent as much as possible and the intent here should be to choose the path of execution based on a comparison. That means, if you're looking for an odd number, you should use something like (num % 2) == 1.
You also don't need a separate printf call in each of those code paths:
printf("%d is %s\n", num, ((num % 2) == 1) ? "odd" : "even");
You'll notice I've also used num instead of i. This is simply a style thing of mine, related to the afore-mentioned intent. If the variable is only used as an index, I'm happy to use the i-type variables(a) but, the second it gains a semantic property (like a number being checked for oddity), I tend to use more descriptive names.
I have no issue with people using simple variable names, I just prefer more descriptive ones in my own code.
(a) Actually, I'd probably use idx in that case but that's being too CDO(b), even for me :-)
(b) OCD but in the right order :-)

C doesn't have a dedicated boolean type. It uses int value as boolean. That is 0 is considered false and any non zero value is treated as true.
Try printing some conditions
printf("%d",5==5);
printf("%d",1>3);
This will output
1 and 0.
C always uses 1 to denote true. But any other non-zero value would work as well when using in conditions.
if(6+1)
printf("TRUE");
Will print TRUE.
This is also the reason we can use this form of while loop:
int i= 10;
while(i--){
printf("%d",i);
}
Will print 9876543210. Notice it stops when i becomes 0, which is false.
Now back to the question, i%2 would always result in either 0 or 1. In case of 1(true) the first statement is run while in case of 0 (false) the second statement is run.

Related

C Integer range must meet 3 different conditions

If I wanted to limit the range of values to be assigned to an integer to three different conditions. eg; Must be between 9 and 95 and also be divisible by 5 would this be the correct way to accomplish this?
I've been told that i can have multiple conditions as long as they are separated by && but I am having little success with my code.
if (input >= 5 && input <= 95 && input %5)
Your code seems fine to me, except for this line.
if (input >= 5 && input <= 95 && input %5)
The expression input % 5 returns the remainder of input/5. You want input to be divisible by 5, which happens when input % 5 returns a remainder of 0. Since C interprets 0 as false, and pretty much all other integers as true, this expression will do exactly the opposite of what you want it to do. Try using
if (input >= 5 && input <= 95 && (input % 5 == 0))
That should do what you want it to do.
There are a number of issues with your code as it stands. First, the outright bugs:
The expression input % 5 will give you the remainder when divided by five. This means you will get zero if it is a multiple, non-zero otherwise. Unfortunately, zero is treated as false so this will only be true if input is not a multiple. The correct expression is (input % 5) == 0.
If you enter something that cannot be interpreted as an integer, the scanf will fail and input will be left at whatever value it was beforehand. This should be caught and acted upon, by checking the return value - this gives you the number of items successfully scanned so should be one.
Your code seems to return the value if okay but return nothing if it's invalid.
Next, while not bugs, these things are my personal preferences which can make code easier to read and maintain:
I prefer to explicitly separate sub-expressions so I never have to worry about precedence rules (provided it doesn't make the expression unreadable in the process). To that end, I would make the full if statement if ((input >= 5) && (input <= 95) && ((input % 5 == 0)).
I'm not a big fan of the if (condition) transferControl else ... construct since the else is totally superfluous.
I also prefer error catching to be done in a localised fashion at the start, catching problems early. Only after all checks are passed do you do the success portion.
A function (assuming it is a function, which seems likely) should generally do one thing, such as check if the value is valid. Writing issues to standard output is probably best left to the caller so that the function is truly re-usable. It would be better to have a function do the check and return some value to indicate whether or not there was a failure, along with the value if valid.
It's usually better to use puts("something") rather than printf("something\n"). The printf call is best left to where you actually need to do argument formatting.
Taking that all into account, the code that I would posit would be along the lines of:
#include <stdbool.h>
bool InputValidRangeAndMultiple(
unsigned *pValue,
unsigned minVal,
unsigned maxVal,
unsigned multVal
) {
unsigned input;
// If no unsigned int available, error.
if (scanf("%u", pValue) != 1) return false;
// If value invalid in any way (range or multiple), error.
if ((*pValue < minVal) || (*pValue > maxVal)) return false;
if ((*pValue % multVal) != 0) return false;
// Value is now deemed okay.
return true;
}
Calling that function can be done thus, with the prompts and errors handled outside the "input and check" function:
#include <stdio.h>
unsigned value;
puts("Enter Value.\nValue must be divisible by 5 and within 5 and 95...");
if (! InputValidRangeAndMultiple(&value, 5u, 95u, 5u)) {
puts("Invalid input...");
returnOrDoSomethingIntelligent();
}
// The 'value' variable is now valid.

Why am I getting the answer "odd" instead of "even"

Why am I getting the answer "odd" instead of "even"?
#include<stdio.h>
#define ODD(x) x%2?0:1
int main()
{
int a=5;
if(ODD(a+1))
printf("even");
else
printf("odd");
return 0;
}
ODD(a+1) expands to a+1%2?0:1. With a as 5, that is same as (5+(1%2))?0:1 or 0.
% beats + which beats ?:
if(0)
printf("even");
else
printf("odd"); // print `odd`
Perhaps you wanted some () to insure evaluation order.
// #define ODD(x) x%2?0:1
#define ODD(x) ((x)%2?0:1)
Yet that seems backwards. How about
#define ISODD(x) ((x)%2 != 0)
See How do I check if an integer is even or odd?
1 is treated as true and 0 as false.
if (1) is executed always, and when you get 0 as result, the branch shifts to else
so code should be :
if ODD is true (returning 1 from terneray expression), print "odd"
#define ODD(x) x % 2 ? 0 : 1
Given an even number x, x % 2 will give you zero, which is false.
Hence the result of the entire ternary expression will be the second option 1, which is true.
You would be better off with something like:
#define ODD(x) (((x) % 2) != 0)
It's both more readable in intent, and less prone to errors such as getting the true/false values mixed up, or being burnt by simple text substitution having unexpected effects.
I do not like this kind if macros for many reasons (one of it that they can be a source of silly errors - like in your case). It should be domain of functions.
int ODD(int x)
{
return x & 1;
}
if you are worried about function call overhead just make it inline (but on any level op optimisation the compiler will inline it anyway as the call is probably longer than the function itself.

Bug in the code

This code is always printing
fine Rs. 1
Despite number of days entered is > 30. What is the reason?
#include<stdio.h>
int main(void)
{
int days;
printf("enter no. of days");
scanf("%d",&days);
if (days<=5){printf("fine 50 paise");}
else if (5<days<=10){printf("fine Rs. 1");}
else if (10<days<30){printf("fine Rs.5");}
else printf(" memebership cancelled");
}
change
if (5<days<=10)
to
if (5<days && days <= 10)
same for other(s).
Otherwise, in your code, the condition check behaves like
if ( (5 < days) <=10)
so, whatever value you enter for days [6 and above, keeping the first if in mind], the result of the < operation will always produce either 0 or 1, both being <= 10, thus making the condition TRUE, printing fine Rs. 1.
Related Reading: C operator precedence.
Note: It's a good practice to add a return statement before the closing } of main()
C parses statements (such as if(5<days<=10)) in pieces, rather than trying to interpret them holistically. What this means is that the compiler reads if(5<days<=10) as if((5<days)<=10). Note that this means that the result of 5<days is compared to 10, not the variable days. To expand, the result of any comparison operator (<, >, ==, etc) is an integer representing whether it is true or false (this is called a boolean value, a value which is either true or false), 1 or 0 respectively. So, assuming 5<days is true, the next comparison is 1<=10 (or 0<=10 if days is smaller than 5), which of course is always true.
To fix this, use the comparison operator && (and). if(5 < days && days <= 10) is parsed as ((5 < days) && (days <= 10)), so you are correctly first comparing the days variable to 5 and 10, then taking the truth value of each of those statements and seeing if 5 < days and days <= 10 is true.
One last point - 0 is always false, any non-zero is always true, so if(0) will always be false and if(5) will always be true.
It's due to the second if condition, i don't know if it is allowed to use condition the way you used in you code as:
if (5<days<=10)
edit it to
if(days > 5 && days <= 10)
and it will work, also edit the third condition accordingly.
if (5<days<=10)
is not of the right syntax
it should be
if(5<days && days<=10)
change it and your problem should be solved. :)

Difference between return 0 and return 1

My professor posted
int main(int argc, char **argv)
{
// enter code here
printf("Test 1: trying odd(3) AND even(2)...\n");
printf("%d\n", odd(3) && even(2));
printf("Test 2: trying odd(3) OR even(2)...\n");
printf("%d\n", odd(3) || even(2));
printf("Test 3: trying odd(4) AND even(7)...\n");
printf("%d\n", odd(4) && even(7));
printf("Test 4: trying odd(4) OR even(7)...\n");
printf("%d\n", odd(4) || even(7));
return 0;
}
int odd(int n)
{
printf("in odd!\n");
return n % 2 == 1;
}
int even(int r)
{
printf("in even!\n");
return r % 2 == 0;
}
as an assignment asking why lines 2 and 3 only return in odd! but 1 and 4 return in odd! and in even! I'm unsure as to why as I don't know the difference between the Return 1 and Return 0 commands. From what I can gather Return 1 will always return the value (in this case in odd!) but return 0 will only return it if it satisfies a certain condition?
Also: does the code int length(char *name,int start,double finish): return the length of a word in characters as a real number?
Thanks in advance to anyone that decides to help me.
This is called "Short-circuit evaluation".
...in which the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression...
Therefore, you have to figure out what will these two functions odd and even return:
odd(): If n % 2 == 1 , return 1, otherwise 0
even(): If n % 2 == 0 , return 1, otherwise 0
And in the main() function,
odd(3) AND even(2): odd(3) return 1, and check the return value of even(2), therefore the even() is called.
odd(3) OR even(2): odd(3) return 1, because of 'short-circuit evaluation', it doesn't need to check the even(2), therefore the even() isn't called.
odd(4) AND even(7): odd(4) return 0, because of 'short-circuit evaluation', it doesn't need to check the even(7), therefore the even() isn't called.
odd(4) OR even(7): odd(4) return 0, and check the return value of even(7), therefore the even() is called.
when evaluating a logical expressions, it checks the condition one by one and whenever the whole expression is known (whatever the remaining are) it stops evaluating them.
Example
unsigned char a = 1; // true
unsigned char b = 0; // false
case 1
if (a && b) printf("Yes");
check a: yes it is true
check b: no it is not true
Result: the expression is wrong and it doesn't print Yes
case 2
if (a && !b) printf("Yes");
checks a: yes it is true
checks b: yes it is false
Result: the expression is right and it prints Yes
case 3
if (a || b) printf("Yes");
checks a: yes it is true
checks b ?!!! WHY? no need to check b since the whole expression result is known only by checking a, do you agree?
Result: checks aand print Yes without even checking b
Project that on your code now ;)
Return 0; - the function returns 0.
Return 1; - the function returns 1.
In your case odd function returns 1 when number (n) is odd and 0 when the number is even.
This is done by "asking" if the reminder when dividing by 2 equels 1.
Also even function returns 1 when number (r) is even, and 0 when the number is odd.
This is done by "asking" if the reminder when dividing by 2 equels 0.
In your main function, and (&&) and or logical operations are done, on the results of the return values of odd and even functions.
Example:odd(3) return 1, even(2) return 1 then 1&&1 equals 1 (the result).
The logical Boolean algebra operators AND and OR (&& and ||) in C operate with an optimization known as short-circuit evaluation.
This is how the optimization works.
Imagine that you came up with a rule for yourself:
You will only date someone if they own a cat AND a dog AND a fish.
Now imagine you start talking to someone that you may be interested in dating. They say:
Well, I have a cat, I don't have a fish, but I do have a dog.
When did you stop paying attention to what they said? As soon as they said that they didn't have a fish, because as soon as they said that, they broke your "AND" rule. So, the rest of the sentence is completely irrelevant. This is short-circuiting AND.
Now imagine that you changed your rule:
You will only date someone if they own a cat OR a dog OR a fish.
Now imagine you start talking to someone that you may be interested in dating. They say:
Well, I don't have a cat, I have a fish, and I don't have a dog.
When did you stop paying attention to what they said? As soon as they said that they had a fish, because as soon as they said that, they satisfied your "OR" rule. So, the rest of the sentence is completely irrelevant. This is short-circuiting OR.
Short-circuit evaluation is a performance optimization for evaluating logical expressions.
In your example, the even() function returns true if the number passed to it is even, and the odd() function returns true if the number passed to it is even. Otherwise these functions return false. Look at each of the Boolean expressions and notice when short-circuit evaluation must occur.
There's also another way to test for even values for integral types.
int IsOdd(int x) { return (x & 1); }
int IsEven(int x) { return !(x & 1); }
If the least-significant bit is set, the number is odd. If not, it's even. This simply tests that bit. Just throwing this out there so you can eliminate the modulus operation... it's another option. Not an answer to your question, but I can't comment so...
As we know 0 indicates false-ness, 1 indicates true-ness. And the return part tells the compiler that the function must return the evaluated result to the caller module.
So, a return 1 means signal the caller module about a successful execution of the called module (with the aid of a Non-Zero quantity i.e. 1)
whereas,
return 0 presents a flag showing that there was some error/anomaly that led to the termination of the called module. So, in this case stderr shall be used to give details about such error.

For loop without the second condition, i.e. the boolean check?

I have to write a function that calculates the floor of log base 16 of an unsigned int passed in. There are restrictions as to what operators and what constants we are allowed to use, and we can only use specifically for loops.
For clarity, we cannot use any conditional statements(if, else, switch ... ). The function prototype is:
int floor_log16(unsigned int x);
Allowed operators: ++ -- = & | ~ ^ << ! >>
Allowed constants: 1 2 3 4 8 16
I wrote a version of the program as follows:
int floor_log16(unsigned int x) {
int index=1;
int count=(1!=1);
count--;
for(; index<=x; index<<=4) {
count++;
}
return count;
}
which seems to work as desired. However, I realized that based on the later functions and description of the needed functionality we have to write, I noticed that under "allowed operators" sometimes > and < were listed.
I deduce this implies that since for the floor_log16 function listed above, we weren't explicitly told to use > or <, I can only assume that the solution posted above will not be accepted.
This leaves me rather confused because I don't understand how you can possibly have a for loop without a boolean check?
Isn't the whole idea of a loop to iterate while a condition is met?
Well, first of all, for-loop without the boolean check is perfectly fine. For example,
for (;;)
is a common way of writing
while (true)
Second, having a for-loop with other parts but without boolean check is still useful as you can exit it with return or break.
And the last thing. There are tons of ways of getting a boolean without using < and >. For example, you can simply use i to check that i != 0 and so on.
For example if you want to check that a < b you can check for (a - b) < 0 instead. Implementing addition (and hence subtraction) with bitwise operators is a well known interview question (you should really try to do this yourself, it's fun), and checking that your int is negative is as easy as looking at its most significant bit.
I don't like to spoil your task but consider about for condition like 'comparison to 0'. This doesn't require any explicit operator. One of possible way to get it is something like this:
// This cycle will end as soon as index is 0.
for (;index; index = (index >> 4))
{
// ...
}
If you XOR any unsigned with itself, it becomes 0. So int count=(1!=1); could be changed to int count = 1 ^ 1.
As for the loop condition, Roman's idea of comparison to 0 seems like the most natural way to go.

Resources