True and False with Operators - c

me again ... Sorry for asking maybe a little bit stupid questions but i am a starter and i really want to learn coding .. So i got a problem to realize why those are always true ? Its something with the operators or again C behavior is undefined. ?
int x;
int b;
b = 1 < x < 10;
printf("%d%d",b);
char c = 'z';
(c==' ') || (c='\t') || (c=='\n');
printf("%c",c);
Why those are always true ? Its because of ASCII code or what ?

Result of comparison of constant 10 with boolean expression is always true
You can see here a table for the C Operator Precedences
it could be read like this:
b = ((1 < x) < 10);
being that in languages such as C, relational operators return the integers 0 or 1, where 0 stands for false and any non-zero value stands for true.
so the value stored in b is 1 (true)
Also:
you're not initializing x, it should have trash info (probably != false)
and in your second code, you're allocating instead of comparing, (c='\t') is this on purpose? That's the reason it's printing a 'tab'.

In your first block of code, there are several problems:
x is uninitialized (you did not give it a value)
1 < x < 10 is not valid C
your printf statement expects 2 integer values to accompany the "%d%d", but you are only passing 1
I think this is what you want:
int x = <some valid value>;
int b;
b = ((1 < x) && (x < 10)); // expression is true if x is between [2..9]
printf("%d",b);
This line
(c==' ') || (c='\t') || (c=='\n');
Should be
(c==' ') || (c=='\t') || (c=='\n');
Note the double equals when comparing to \t (the tab character). Otherwise, you wind up assigning a tab char to c.

Related

Why multiple if works and if else does not it this case [duplicate]

This question already has answers here:
Chaining multiple greater than/less than operators
(6 answers)
Two '==' equality operators in same 'if' condition are not working as intended
(4 answers)
Math-like chaining of the comparison operator - as in, "if ( (5<j<=1) )" [duplicate]
(4 answers)
Closed 3 years ago.
I'm learning C and I've came around a strange problem. I think I understand the difference between multiple ifs and else-if statement, but I simply can not understand the difference in behavior this time. If I delete the else keyword it works as intended, but with else on it does not.
The code is about counting of occurrences of each letter without differentiating lower case or upper case (so 'a' and 'A' both counts as 1 occurrence for letter 'a').
I've tried omitting braces where I could but nothings changed so I've left them in to avoid caveats.
while ((c = getchar()) != EOF)
{
if ('A' < c < 'Z')
{
++array[c - 'A'];
}
else if ('a' < c < 'z')
{
++array[c - 'a'];
}
}
When I type in 'a' then the array is not being incremented, but if I delete the else statement thus switching to a multiple if situation, it works as intended. Letter 'A' updates the array nicely in both cases.
Could you please help me understand the difference in behavior in this case?
What we need to know:
The result of < comparison is an int with value 1 for true and 0 for false. It's like the result of 1 + 3 is int with value 4, the same way the result of 1 < 3 is an int with value 1.
Operator < has associativity Left to Right. That means that in 1 < 2 < 3 it will be parsed as (1 < 2) < 3 - ie. first will be 1 < 2 calculated, then the result will be < 3 compared with 3.
So:
'A' < c < 'Z'
is interpreted as
('A' < c) < 'Z'
The result of 'A' < c is either 1 or 0. When 'A' is lower then c, then it becomes:
1 < 'Z'
otherwise it becomes:
0 < 'Z'
Both cases are true, so the comparison is always true.
If you want to check if a number is a letter between A and Z including the letters A and Z, you can:
if ('A' <= c && c <= 'Z') {
or #include <ctype.h> and use isupper function:
if (isupper(c)) {
try
while ((c = getchar()) != EOF)
{
if ('A' <= c && c <= 'Z')
{
++array[c - 'A'];
}
else if ('a' <= c && c <= 'z')
{
++array[c - 'a'];
}
}
'a'<c<'z' is computed not like a mathmatical expression, first 'a' < c is evaluated to True or False then that value (converted to 0 or 1 probably) is compared to 'z', so it is not doing what you are expecting it to.
The relational operators like < take two operands and returns 1 if the first operand is smaller than the second, otherwise 0.
Thus 'A' < c gives a result of 1 or 0, and then (since < operators associate left-to-right) you compare the value 1 or 0 with the ASCII value of 'Z', which is nonsense.
Correct code for checking if a variable is inside an interval is
if ( (c >= 'A') && (c <= 'Z') )
Also make sure c is int and not char, because getchar actually returns int, and to compare against EOF you will need to use int.

C languange 4 digit possible variations with exception

So i have a homework, but i can't wrap my head around why this code doesn't work.
Problem sounds something like this:
Make a code that checks all possible variations of 4 digit number, but there are no 3 same digits in a number. ( i hope that makes sense)
My code:
#include<stdio.h>
int main ()
{
int i;
char a,b,c,d;
for (i=0; i<9999; i++)
{
a = i/1000;
b = i/100%10;
c = i/10%10;
d = i%10;
if (a==b==c) {i++;}
else if (b==c==d) {i++;}
else if (c==d==a) {i++;}
else if (d==a==b) {i++;}
else if (a==b==c==d) {i++;}
else
{
printf("%d,%d,%d,%d\n", a,b,c,d);
}
}
}
I want it to print out something like this:
0,0,1,1
0,0,1,2
0,0,1,3
...
0,1,0,9
0,1,1,0
0,1,1,2
...
9,9,8,8
Instead it prints:
0,1,2,2
0,1,3,3
0,1,4,4
0,1,5,5
0,1,6,6
...
0,8,6,6
0,8,7,7
0,8,8,8
0,8,9,9
0,9,2,2
...
9,9,9,8
There's a problem with these comparisons:
if (a==b==c)
This doesn't find out if a, b and c are all the same. The result of == is 0 or 1, and then that is compared to the third number. So per example if all three numbers are 9, then 9==9==9 turns into 1==9, which is 0, so the if is not taken. What's more, you have false positives for things like 9==9==1.
What you instead need here is
if ((a==b) && (a==c))
Now you check if a is equal to b, and when it is, you check it with c, and the if is taken if they're all the same.
Likewise of course for the other comparisons, so instead of else if (a==b==c==d) you want else if ((a==b) && (a==c) && (a==d))
As other answers have noted, you can't chain comparison operators in C and get the expected results. Use logical operators to combine comparisons. It would probably be more clear to use || to avoid all of the else statements.
There is another significant problem with the posted code: i is incremented whenever a failing number is found. But then i is incremented again by the for loop. This causes the number after a failing number to be skipped, so some desired numbers will not be found. For example, 3222 should fail, and the subsequent number 3223 should pass, but this number is skipped by the posted code (after the comparison corrections), with the next number to be checked 3224. Instead, just use continue:
if ((a == b && a == c) ||
(b == c && b == d) ||
(c == d && c == a) ||
(d == a && d == b) ||
(a == b && a == c && a == d)) {
continue;
} else {
printf("%d,%d,%d,%d\n", a,b,c,d);
}
You can't use multiple equalities like this. You have to do them separately with and conditions (e.g. a==b && b==c).

C: Why Bitwise AND works for special character

I'm trying to write simple program using c to compute the intersection between two strings using Bitwise AND operator Like :
char x[]="abcdefghijklmnopqrstuvwxyz";
char y[]="abcdefghijklmnopqrstuvwxyz";
int i,sum=0;
const int size = 26;
for(i=0;i<size;i++)
{
if(x[i]&y[i]==y[i]){
printf("%c",y[i]);
sum++;
}
}
printf("\n%d\n",sum);
After executing code i found the result :
acegikmoqsuw
13
what's the problem with my code or what's the reason for that ?
You should take care of operand precedence in the if:
char x[]="abcdefghijklmnopqrstuvwxyz";
char y[]="abcdefghijklmnopqrstuvwxyz";
int i,sum=0;
const int size = 26;
for(i=0;i<size;i++)
{
if((x[i] & y[i]) == y[i])
{
printf("%c",y[i]);
sum++;
}
}
printf("\n%d\n",sum);
Your code isn't strictly correct; if every x[i] were 0xff then it'd think that every character matched. All you're going to detect is anywhere that the relevant x has a 0 that the relevant y does not.
If the requirement is to use &, for whatever academic purpose, then run the test in both directions:
if( (x[i]&y[i])==y[i] && (x[i]&y[i])==x[i] )
i.e. if there are no bits set in y that are not also set in x and there are no bits set in x that are not also set in y then the two must have the same bit pattern.
Though, obviously:
if( x[i]==y[i] )
... is the intended means of testing for equality in C.
Your problem lies in the evaluation of the if statement
if(x[i]&y[i]==y[i])
the == operator has greater precedence than the & operator.
https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
Try replacing it with this:
if( (x[i] & y[1]) == y[1] )

Why the "if constraint" not working in the code?

The first if statement is not working and code is running without considering the constraint.
#include <stdio.h>
int main(void)
{
int with;
int inacbal;
float acleft;
scanf("%d",&with);
scanf("%d",&inacbal);
if(0<=with<=2000&&0<=inacbal<=2000) //this statement not working
{
if((with%5)==0)
{
if(inacbal>with)
{
acleft=(float)inacbal-(float)with-0.50;
printf("%.2f",acleft);
}
else
printf("%d",inacbal);
}
else
printf("%d",inacbal);
}
return 0;
}
Even on inputting value greater than the constraint relation the loop is running.
While mathematicians sometimes use the shorthand a < b < c, the C language is a bit more strict.
You must rewrite:
if(0<=with<=2000&&0<=inacbal<=2000)
to be something like:
if((0 <= with) && (with <= 2000) && (0 <= inacbal) && (inacbal <= 2000))
What you have actually is valid C but it does not do what you would normally expect. The expression 1 < 2 < 3 actually means: calculate 1 < 2 (giving the integral truth value 0 or 1 for false and true respectively) then comparing that against 3.
If you want to use a shorter form, you can use something like:
#define between(a,b,c) (((a) <= (b)) && ((b) <= (c)))
:
if (between (0, with, 2000) && between (0, inacbal, 2000))
though you need to watch out for duplicated side effects if you use terms such as a++ when using it. A safer approach may be replacing the macro with something along the lines of:
int between (int a, int b, int c) {
return (a <= b) && (b <= c);
}
You cannot compare avariable to two other values like that. You should separate the conditions:
if ((0<=with) && (with<=2000) && ( 0<=inacbal) && (inacbal<=2000))
The statement
if(0<=with<=2000&&0<=inacbal<=2000)
is not checking variables between the given range. These comparisons doesn't have mathematical meaning in C.
Compiler should raise a warning
[Warning] comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
To check whether a value is between a given range or not you need to use && operator. You need to rewrite it as
if(0 <= with && with <=2000 && 0 <= inacbal && inacbal <=2000)

Assign and compare in a single statement in C

How can I convert the following code to a single line?
int *i;
i = some_func_ret_int_ptr();
if(!i)
{
// Do something
}
// Will use 'i' later
I want to do something like:
if((i=some_func_ret_int_ptr) && !i)
{
// Do something
}
// Will use 'i' later
But I am wasting one comparison here. Is there a better way to do it?
All I want is assignment and comparison in the if and compare only i.
With C, this is as far as you can golf it:
int *i;
if(!(i = some_func_ret_int_ptr()))
{
// do something
}
// Will use i later
In addition to what is suggested in other answers, you can also do it as
if (i = some_func_ret_int_ptr(), !i)
{
// Do something
}
It is a literal implementation of what you had originally, with the statement sequence replaced with an expression sequence separated by the , operator.
It does not make much practical sense, though.
You can do
if(!(i = some_func_ret_int_ptr()))
{
...
}
What happens in this code, in order, is:
The return value of some_func_ret_int_ptr() is assigned to i
The statement !i is checked
If i == 0 what's inside the if gets executed, otherwise it will not
Clean and readable:
int * i = some_func_ret_int_ptr();
if (!i) { /* ... */ }
An option not mentioned yet is:
if ( NULL != (i = some_func()) )
Using the explicit comparison against NULL makes it very easy to read the intent of this code. Especially considering that your function probably won't have ret_int_ptr in its name.
Using the #include <ctype.h> standard library, to get the toupper(char) function, we can write the following function:
void StringToUppercase(char* str)
{
for (int i=0; (str[i] = toupper(str[i])) != 0; i++); // No for-loop body!
// The expression "(str[i] = toupper(str[i]))" executes first and then returns str[i]
}
so that the statement (str[i] = toupper(str[i])) != 0; both assigns a char and checks to see if it is '\0' or not.
The way this works is that part of the C language specifies that assignment expressions have the value of the lefthand expressions after the assignment. For example, with ints, consider the following code snippet:
int x = 5;
int y = x = 8;
// Assignment operators (= += <<=) have right-to-left associativity.
// The expression `(x=8)` returns the value 8, after it has been executed
int z = x != y; // Comparisons have greater (tighter) precedence than assignment
printf("(x, y, z) = (%d, %d, %d)\n", x, y, z); // prints (8, 8, 0)
Same as M.M's answer, but I would go with:
if ((i = some_func_ret_int_ptr()) != NULL)
As it makes the execution order clearer.

Resources