The K&R c says: The precedence of && is higher than that of ||
but why The following code, the c and d is still -1:
int a, b = -1, c = -1, d = -1;
a = (b = 1) || (0, c = 0) && (1, d = 0);
Because && has higher precedence than ||, your statement parses like this:
a = ((b = 1) || ((0, c = 0) && (1, d = 0)));
So you have (b = 1) as the left operand to || and (0, c = 0) && (1, d = 0) as the right operand. The left operand is evaluated first, so you have 1 on the left side. Because of that, the value of the entire || expression is known so the right side, i.e. (0, c = 0) && (1, d = 0), is not evaluated.
So c and d are not updated.
I just started programming and I have the following task: Write a program that loads integer variables that have values 0 or 1 and then tells if (!a)&b&c + a&(!b)&c + a&b&(!c) + a&b&c is true or false. I wrote this:
int a, b, c;
printf ("a: \n");
scanf ("%d", &a);
printf ("b: \n");
scanf ("%d", &b);
printf ("c: \n");
scanf ("%d", &c);
if ((a==1 || a==0) && (b==1 || b==0) && (c==0 || c==1))
printf ("%d &&(%d||%d) || %d&&%d=%d\n", a, b, c, b &&(a||c) || a&&c );
else
printf ("Numbers are not correct!\n");
I simplified the expression from the beginning and I got: b(a+c)+a*c. When I run this program, the output is not as expected; it is not 0 or 1 even though I take for example a=0, b=1, c=1 (which is what should work according to task, but the output is 4327). Can somebody help me? I use C.
Your problem is that the printf() format string has 6 %d conversion specifications, but you only pass 4 values (a, b, c and the expression). You either need to use the POSIX n$ notation (see printf()), like this:
#include <stdio.h>
int main(void)
{
int a, b, c;
printf("a: \n");
scanf("%d", &a);
printf("b: \n");
scanf("%d", &b);
printf("c: \n");
scanf("%d", &c);
if ((a == 1 || a == 0) && (b == 1 || b == 0) && (c == 0 || c == 1))
printf("a = %1$d, b = %2$d, c = %3$d: (%2$d && (%1$d || %3$d)) || (%1$d && %3$d) = %4$d\n",
a, b, c, (b && (a || c)) || (a && c));
else
printf("Numbers are not correct!\n");
return 0;
}
or you need to repeat the arguments as required:
#include <stdio.h>
int main(void)
{
int a, b, c;
printf("a: \n");
scanf("%d", &a);
printf("b: \n");
scanf("%d", &b);
printf("c: \n");
scanf("%d", &c);
if ((a == 1 || a == 0) && (b == 1 || b == 0) && (c == 0 || c == 1))
printf("a = %d, b = %d, c = %d: (%d && (%d || %d)) || (%d && %d) = %d\n",
a, b, c, b, a, c, a, c, (b && (a || c)) || (a && c));
else
printf("Numbers are not correct!\n");
return 0;
}
The output from both programs is the same. I used a shell script to test b41 (created from b41.c) like this:
for a in 0 1
do
for b in 0 1
do
for c in 0 1
do
echo $a $b $c | b41
done
done
done | grep -v '^[abc]:'
The grep removes the prompt lines (they're boring!) and the output is:
a = 0, b = 0, c = 0: (0 && (0 || 0)) || (0 && 0) = 0
a = 0, b = 0, c = 1: (0 && (0 || 1)) || (0 && 1) = 0
a = 0, b = 1, c = 0: (1 && (0 || 0)) || (0 && 0) = 0
a = 0, b = 1, c = 1: (1 && (0 || 1)) || (0 && 1) = 1
a = 1, b = 0, c = 0: (0 && (1 || 0)) || (1 && 0) = 0
a = 1, b = 0, c = 1: (0 && (1 || 1)) || (1 && 1) = 1
a = 1, b = 1, c = 0: (1 && (1 || 0)) || (1 && 0) = 1
a = 1, b = 1, c = 1: (1 && (1 || 1)) || (1 && 1) = 1
Note that GCC set fussy recommended extra parentheses in the expression mixing && and || operators. It's good to know the precedence rules; it's better to write code to avoid making those reading the code have to remember the rules.
The original expression ((!a)&b&c + a&(!b)&c + a&b&(!c) + a&b&c) is symmetric in a, b, c, yet the revision is not, and I suggested that the simplification was wrong, but it isn't. The original expression is true if any two of a, b, c are true, or if all three are true. On further scrutiny, the alternative (b(a+c) + a*c) does the same — but it could equivalently be written c(a+b) + a*b or a(b+c) + b*c; all three should produce the same output.
but the output is 4327
printf() lacks matching each "%d" with an int argument. Result: undefined behavior (UB): anything may happen including garbage output.
// 1 2 3 4 5 6 1 2 3 v-----4----------v (missing 5 and 6)
printf ("%d &&(%d||%d) || %d&&%d=%d\n", a, b, c, b &&(a||c) || a&&c );
Instead:
// For clarity, do one at a time.
{
printf("a:%d\n", a);
printf("b:%d\n", b);
printf("c:%d\n", b);
printf("Formula: %s\n", "(!a)&b&c + a&(!b)&c + a&b&(!c) + a&b&c");
printf("Formula result: %d\n", (!a)&b&c + a&(!b)&c + a&b&(!c) + a&b&c);
}
The following proposed code:
cleanly compiles
performs the desired functionality, using a table as input
displays the results of the logic equation
and now the proposed code:
// the equation to solve
// if (!a)&b&c + a&(!b)&c + a&b&(!c) + a&b&c
// where: `!` is a symbol for logical not, `&` is logical and, and `+` is logical or.
#include <stdio.h>
int main( void )
{
int a;
int b;
int c;
#if 0
a = getchar();
getchar();
b = getchar();
getchar();
c = getchar();
#endif
int data[][3] =
{
{ 0, 0, 0 },
{ 0, 0, 1 },
{ 0, 1, 0 },
{ 0, 1, 1 },
{ 1, 0, 0 },
{ 1, 0, 1 },
{ 1, 1, 0 },
{ 1, 1, 1 },
};
for( size_t i=0; i< sizeof( data ) / sizeof( data[0] ); i++ )
{
a = data[i][0];
b = data[i][1];
c = data[i][2];
printf( "a=%d; b=%d: c=%d:\n", a, b, c);
if ( (!a && b && c) || (a && b && !c) || (a && b && c) )
{
puts( "true\n" );
}
else
{
puts( "false\n" );
}
}
}
a run of the proposed code results in:
a=0; b=0: c=0:
false
a=0; b=0: c=1:
false
a=0; b=1: c=0:
false
a=0; b=1: c=1:
true
a=1; b=0: c=0:
false
a=1; b=0: c=1:
false
a=1; b=1: c=0:
true
a=1; b=1: c=1:
true
What does this function do that helps it to take input differently and how are the conditions in for loop executed?
void scanint(int &x)
{
int flag=0;
register int c = gc();
if(c == '-') flag=1;
x = 0;
for(;(c<48 || c>57);c = gc());//why is this used?
for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}//how is this executed ?
if(flag == 1)x=-x;
}
It's not c.
void scanint(int &x) {/* Whatever */}
// ^^
This defines a function accepting a reference to an int and there are no references in c, the arguments are passed by value to functions. You could of course use a pointer to an int, but then the body of the function should be changed accordingly, using *x instead of ant occurrences of x.
The following assumes that gc() stands for a function similar to getchar(), so that the posted code is a very bad way of extracting an int value from stdin:
void scanint(int &x) // Or 'int *x' in C
{
int c = gc(); // register was deprecated in C++17
bool is_negative = (c == '-'); // C has bool from C99 too
x = 0; // '*x = 0;' in C. The same applies to the following code
// Considering only ASCII, ignores non-digit characters
// E.g. from " 123" it ignores the first two spaces,
// but, given " -123", it will ignore the sign too. Bad, as I said.
for( ;
( c < '0' || c > '9');
c = gc() )
;
// Now computes the actual number using an old trick that should
// be left to the compiler to be exploited:
// 10 * x = (2 + 8) * x = 2 * x + 8 * x = x << 1 + x << 3 (bit shifts)
for( ;
'0' <= c && c <= '9';
c = gc() )
{
x = (x << 1) + (x << 3) + c - '0';
}
if ( is_negative )
x = -x;
}
I was wondering if we could get rid of all the "if" statements only by using boolean logic.
int main() {
int a,b,c,d;
char e;
scanf("%d %d %d", &a, &b, &c);
scanf("%d", &d);
if (d == 0)
{
e = 'O'*((a+b == c) || (a+c == b) || (b+c == a));
e += (e == 0)*'X';
printf("%c\n",e);
}
if (d == 1)
{
e = 'O'*((a*b == c) || (a*c == b) || (b*c == a));
e += (e == 0)*'X';
printf("%c\n",e);
}
}
So far I've been able to replace
if ((a+b == c) || (a+c == b) || (b+c == a))
{
e = '0';
}
else
{
e = 'X';
}
by
e = 'O'*((a+b == c) || (a+c == b) || (b+c == a));
e += (e == 0)*'X';
is there any way to get rid of the lines
if (d == 0)
and
if (d == 1)
using the same logic?
As you wish, no if-statement left:
!d && (
(e = 'O'*((a+b == c) || (a+c == b) || (b+c == a))),
(e += (e == 0)*'X'),
printf("%c\n",e)
);
d-1 || (
(e = 'O'*((a*b == c) || (a*c == b) || (b*c == a))),
(e += (e == 0)*'X'),
printf("%c\n",e)
);
I abused short-circuiting of ||, && and the comma-operator ,.
Anyway, if you want to see the masters in obfuscation, look at
The International Obfuscated C Code Contest .
Speaking about the motivation of this, it is a good thing if you are concerned about efficiency, as conditional branches are very time-consuming (this is the reason there are some complicated mechanisms for branch prediction). But it is not a good practice in usual code, as it might be very hard to understand for your reader, so your code becomes very hard to maintain. Also, as you are a beginner, it is a very good exercise.
Now, keep in mind that there is always a way. It is worth mentioning that you have a combination of logical, bitwise and arithmetic operation. It could be done purely with bitwise operations.
Let's try to make it using just bitwise operations. Assume your code is:
if (d == 0)
e = A;
if (d == 1)
e = B;
, where A and B are those 2 values you compute for e.
Firstly, extend the last significant bit to all of the d's bits (so if d is 1, it should be 0xFFFFFFFF and if it is 0, it should be 0x00000000). Then, do the operation. I splitted them into multiple lines, but it could be done more compact.
d = d << 1 + d;
d = d << 2 + d;
d = d << 4 + d;
d = d << 8 + d;
d = d << 16 + d;
e = (B & d) || (A & ~d);
Note that here I assume an int is 32 bits, which is not very portable. But, it is just an exercise.
#include <stdio.h>
int main()
{
int a = 10, b = 5, c = 5;
int d;
d = b + c == a;
printf("%d", d);
}
In the above code,could any one please explain to me how d = b + c == a works?
Because of operator precedence, it is parsed as
d = ((b + c) == a);
b + c is 10, which is equal to a, so d receives the value of 1, which is how C represents true comparisons.
Based on precedence of operators, binary + has higher precedence than ==. So the statement will be grouped as,
d = ( b + c ) == a;
Which becomes,
d = ( ( b + c ) == a ); // ==> d = ( 10 == 10 );
So, d holds the truth value based on the comparison (b+c) == a which is 1 because in C comparison operators will return 1 for true and 0 for false.
Its works like this
d = (b+c) == a --> (5+5) == 10 ---> 1
Which returns 1
+ operator has higher precedence than ==.So d=b+c==a; parsed as d=((b+c)==a);. b+c is 10.
so (10==a) evaluates true .So d=1;