Output of this C program i can't understand - c

I am revising C again and was making some test programs. At one program I was checking a condition which was translating ino this condition.
#include <stdio.h>
int main()
{
if(0 <= 3000.000000 <= 2000.00){ //this is the condition
printf("3000 is less than 2000, whoa.. \n");
}
return 0;
}
The output is always this print string. I can't understand why.
P.S
I am testing the middle value, i.e 3000.000000 here, but it can be some variable.

The condition is parsed like this:
if((0 <= 3000.000000) <= 2000.00){
The first part, (0 <= 3000.000000), is true, and evaluates to 1 in the comparison with 2000.00. And 1 <= 2000.00 is true.
If you're trying to test whether a value a lies between two values b and c or is equal to either, then you need an expression along the lines of
(a >= b) && (a <= c)

You're getting caught by the fact that in C, booleans are integers: either 0 or 1.
So that line is interpreted left-to-right: First 0 <= 3000, which is true so it ends up as 1. Then that value is fed into the next half, (1) <= 2000, which is obviously true.

It will prints the string in printf.
Because the condition is static.
The 0 is always less than 30000.000000. For the next condition the output of the first condition returns 1. it checks using the 1.
The second condition checking is 1 <= 2000.00. This condition is also true.
So, only this prints the string.

the first condition evaluates to 1 as output and further 1<2000 is checked which is also true.So,the string is printed.

Related

Confusion with operator '!' in c

I've seen the operator ! being used in multiple places differently and I still don't get how it actually works. My basic understanding is it reverses the value from true to false and vice versa. If it reversed to true the statement triggers. Let's take an example.
int main(void)
{
int a = 5;
if (!(a == 6))
{
printf("unlike\n");
}
if (!(a == 5))
{
printf("like\n");
}
}
In the code above since a is 5 it ends up printing "unlike" because the false statement that a is 6 got reversed. Now let's take another example.
int main(void)
{
string i = "abc";
string j = "cab";
string k = "abc";
if (!strcmp(i, j))
{
printf("unlike\n");
}
if (!strcmp(i, k))
{
printf("like\n");
}
}
The string type has been taken from the cs50.h header and strcmp from string.h. strcmp returns value 0 if the two strings are alike and if unlike depending on the alphabetical order returns a positive or negative value. Now if we follow the logic in the previous example, since i and j are unlike, and false it should be reversed to true and unlike should be the output. But I tried running the code and the result was like.
I am confused. Can anyone please explain this to me clearly? Feel free to use other examples too. I could always get away with not using ! but I just want to learn what it is and how to properly use it.
A boolean in C is an integer with zero for false and non-zero for true.
strcmp returns 0 when the compared strings are identical and a non-zero value depending on the difference otherwise. Therefore, strcmp(i,k) is seen as "false". The ! then changes this to "true", which leads to your current output.
In the first case a = 5. then if (!(a == 6)); here a = 6 is not true (false), so it's something like this. if (!(false)) it means if (true). That's why it prints "unlike".
strcmp(i, j) returns 0 if the strings i and j match; otherwise, it will return a non-zero value. In your case,
(!strcmp(i, j))
Here i and j are not equal so strcmp will return a non-zero value because i != j. So !(1) means not(1) means 0, so the if condition is false because of zero. Therefore it'll not execute the printf("unlike\n") line.
(!strcmp(i, k))
Here i and k are same so strcmp will return 0. !(0) means not(0) = 1 so the if condition is true. It will execute the printf("like\n") line.

Why isn't there any condition checking in the following for loop?

for (i = 0; isspace(s[i]); i++) { ... }
The above for loop is the part of the program for converting a string to an integer in K&R on page 61.
There's no condition check in that for loop. How does it work?
The loop terminates whenever the condition expression evaluates to 0. If for instance you see an expression like i < 3, you can think of it as (i < 3) != 0. So in this case, it's isspace(s[i]) != 0 meaning it terminates at the first character that is not a space.
isspace(s[i]) is the condition, since it returns a zero value for 'false' (i.e. the provided character is not a space character), and non-zero values for 'true'. In this case, only one space character exists, but in other functions such as isalpha or isalphanum, non-zero values mean different things like 1 means it is an upper-case letter (so it is an alphabetical character), or 2 means it is a lower-case letter) and so on (I may have mixed those numbers up :/).
In otherwords, the for loop is treating this function as returning a boolean value, like most other expressions, meaning it treats zero-values as false, and non-zero as true.
First of all, you're going to get out of bounds, which is gonna give you a segfault. You're just increasing i, but not checking whether it's still in the bounds or not. For example, what if s would be equal to " "? isspace(i[0]) will return a non-zero value (treated as true) and the loop will continue and will try to access the second (non-existent!) value of s. You'd better add another tiny check: for (i = 0; (i<SIZE_OF_S) && isspace(s[i]); i++) { ... }
Let's now talk about the missing condition. No, it's not missing, it's here: isspace(s[i]). This function checks whether s[i] is considered space or not. It returns a non-zero value if yes, and 0 otherwise (docs). So, it is the missing condition, just in a slightly different form (maybe you're used to different comparisons, but there exist a lot more ways.
Yes If the for loop have without condition checking , the for loop will exit whenever the condition part will be zero
For example
`
int i ;
for (i=0; 7-i; i++)
printf("hello world \n");
getch();
return 0;
}`
See the above program the 'i' minus the seven each time . and the loop will exit whenever the value of condition part will be zero (ie 7-7) .

Array-member comparison in a function not working

First of all I'm not even sure whether you call it a member, couldn't think of a better term.
I'm trying to learn basics of debugging and arrays - so I wanted to create something resembling insert-sort from memory (so mistakes would be made) and then debug the program.
void findingsmaller (int *array, int num_inputs){
int a = 0;
int b = 1;
for ( b=1; b == num_inputs-1; b++ ) {
if ( array[a] > array[b] ) {
goleft(array, a, b);
a++;
}
}
}
Let's say we have this in array: 6 5 3 1 8 7 2 4. array[a] should be 6 and array[b] should be 5. 6 > 5 so we should enter the function that would find the first smaller number on the left of the array.
From my debugging session it seems like the condition is FALSE so I don't enter goleft at all. More specifically, Step into ignores it, the testing printf wasn't executed either. I'm assuming the array comparison is not written properly, what's the correction?
WHOLE CODE if somebody wants to see other possible mistakes.
Thank you in advance!
EDIT: <= num_inputs is correct, somehow I thought for has (range1, range2, change) instead of (start, condition, change). Anyway, now the problem seems that my goleft function does its do-while cycle one time too many although it shouldn't get past that condition.
EDIT2: A couple of other mistakes were fixed.
My printing in main is now for( ; i <= num_inputs-1; )
My goleft would do too many iterations due to the condition, fixed into ... while ( a >= 0 && array[a] > array[b] )
My findingsmaller would only operate if the number next is smaller but does nothing when the number is greater. For example for 6 8 the program wouldn't function properly. Added else {a++}
My fixed code for anyone interested in the comparison of the changes.
The for loop is executed as long as the condition is True.
for ( ;Condition; )
{
// body
}
In your for loop, the condition is always False if the input is greater than 1.
Instead of b == num_inputs - 1, you should put b < num_inputs in your for loop condition. Since the equality isn't true on the first iteration of the loop, it is immediately breaking.
I was looking a little bit at your code and i notice something that doesnt work.
while (scanf("%d", &array[i]) != EOF)
As the documentation of the function scanf say :
The return value is EOF for an error
your while condition was making you num_imputs reaching 200 even if there was only 3 inputs. I would replace EOF by '\n'.
while (scanf("%d", &array[i]) != '\n') /* stop when the user input '\n' you
can replace with any character you want to make it stop. */
I did not make a lot of test but this should make your program work fine.

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. :)

Understanding the basics of the for loop in C language

can anyone explain the working of the for loop in the following code:
#include<stdio.h>
#include<conio.h>
int main()
{
char i=0;
for(i<=5&&i>=-1;++i;i>0)
printf("%d\n",i);
getch();
}
Let's break the for statement down, we have three phases, the initialiser, the test, and the modifier:
for(<Initialiser>; <Test>; <Modifier>)
<content>;
In your case:
for(i<=5&&i>=-1;++i;i>0)
// initialiser: i<=5&&i>=-1;
// test: ++i;
// modifier: i>0
The initialiser is done first. Here no assignment is done. Two boolean expressions (denoted by the >= and <= operators are compared in a logical &&. The whole initialiser returns a boolean value but it doesn't do anything. It could be left as a blank ; and there would be no change.
The test uses the pre-increment operator and so returns the result of i+1. If this result is ever 0 it evaluates as false and the loop will terminate. For any non-zero value it evaluates to true and continues. This is often used when i is initialised to a value less than zero and so the test will increment i until i+1 results in a zero, at which point the loop terminates.
Finally we have the modifier, which in this case simply uses the > operator to evaluate to a boolean value. No assignment is done here either.
The fact is that you've gotten the test and the modifier confused and put them in the wrong positions but before we sort that out let's see how it would work…
We begin with:
char i = 0;
…and for all intents and purposes this does the same thing as our for loops initialiser would do in normal circumstances. The next thing to be evaluated is the for loop's initialiser:
i<=5 && i>=-1;
Because i is 0 it is less-than-or-equal-to 5 and it is greater-than-or-equal-to -1. This expression evaluates to 1 but nothing is done with that value. All we've done is waste a bit of time with an evaluation.
Next up is the modifier to test whether or not the for loop's inner block should be executed:
++i;
This evaluates to 1 and also assigns that value to i. Now, as it's evaluated to a non-zero number, the loop executes:
printf("%d\n",i);
And the digit 1 is printed to the screen... Now it's the modifier that gets executed:
i>0
Well, i is 1 so that is greater-than 0. This evaluates to 1 (or true). Either way, this is ignored. The purpose of the modifier isn't to test or check anything. It's there so that you can change the state of the program each time the for loop iterates. Either way, the loop repeats and it will do this for a very long time. Why? Because ++i is going to evaluate to a non-zero number for a while. Whether or not it will ever terminate depends on how your system deals with integer overflows.
This is what you meant to do:
#include<stdio.h>
#include<conio.h>
int main()
{
for(char i=0; i<=5&&i>=-1; ++i)
printf("%d\n",i);
}
Do you see the difference? Our initialiser now starts the loop with the state of i as zero. We then test if it's within the bounds of -1 to 5 and each time we iterate we increment i by 1. This loop will output:
0
1
2
3
4
5
This snippet:
for(i<=5&&i>=-1;++i;i>0)
printf("%d\n",i);
Does the same as this:
i<=5 && i>=-1; //statement with no effect
while(++i)
{
printf("%d\n",i);
i>0; //statement with no effect
}
So, it's going to print i until ++i evaluates to 0. This will happen after i overflows and becomes negative, then incrementing towards 0. That will take 255 iterations to happen, since chars can store up to 256 different values.
for ( variable initialization; condition; variable update ) {
}
the variable initialization phase is done only once when the for loop starts.
the condition is checked everytime before running code inside the loop. if the condition is false then the loop is exited.
the variable update is done after the first iteration, from the second iteration it is done before the condition check.

Resources