if/else logic using NULL - c

I'm not sure if I understand the conditionals using = NULL and != NULL.
Is this
if (somethin->example == NULL)
{
do task A
return;
}
else
{
do task B
}
the same as this?
if (somethin->example != NULL)
{
do task B
}
else
{
do task A
return;
}

Yes, they are equivalent.
== is the inverse of !=. If you both invert the condition and swap the if and else blocks the two changes cancel out. These are equivalent:
if (a)
{
foo();
}
else
{
bar();
}
and
if (!a)
{
bar();
}
else
{
foo();
}

Yes. They are the same, the only difference is the order of comparison (is NULL vs. is not NULL)
and the order of operation blocks that go below the if statement based on the conditions written and conditions met.
if (x == y) {
do(x);
} else {
do(y);
}
is the same as
if (x != y) {
do(y);
} else {
do(x);
}
So the difference is that in the first sample we are evaluating that x is equal to y, so precedence of "equal" takes place, while the second sample we are evaluating that x is not equal to y, therefore precedence of "not equal" takes place.

Related

Can I use an if statement as condition in another if statement in C?

Can I do that? I´ve searched for an answer, but I couldn´t found any. What I want to do is this:
if(a==5)
{
printf("25");
}
if((if(a==5))==TRUE)
{
printf("\n30");
}
Is this permissible in C?
Can I use an if statement as condition in another if statement in C?
No, you can´t do that, it isn´t syntactically correct. You would get this or a similar error for the inner if test, if you would attempt to compile code that has any occurrence of that in its source code:
error: expected expression before 'if'
But it is already redundant since you can proof several expressions inside just one if statement´s condition test by using the logic operators &&(AND) and ||(OR):
int a = 5;
int b = 10;
if(a == 5 && b == 10) // If a is 5 AND b is 10. - true
{
/* some code */
}
or
int a = 6;
int b = 10;
if(a == 5 || b == 10) // If a is 5 OR b is 10. - true
{
/* some code */
}
Given your example:
if(a==5)
{
printf("25");
}
if((if(a==5))==TRUE)
{
printf("\n30");
}
The inner if statement inside the condition of the outer if statement - if((if(a==5)) == TRUE) isn´t permissible but also redundant, because an if statement proofs on its own whether the condition or a sub-expression is true or not.
Thus, if((if(a==5)) == TRUE), if((a==5) == TRUE) and if(a==5) would be all equivalent, if a if condition test inside the condition of another were permissible and the if statement shall somehow be evaluated to 1.
So even in this surreal case, the code in the example would be equivalent to:
if(a==5)
{
printf("25");
printf("\n30");
}
This
if(a==5)
{
printf("25");
}
if((if(a==5))==TRUE)
{
printf("\n30");
}
can be rewritten this way with keeping the same logic
int condition;
if( ( condition = a == 5 ) )
{
printf("25");
}
if( condition )
{
printf("\n30");
}

Better alternatives for switch statements

I know that this has been already discussed, and there are multiple answers to it. See Performance of array of functions over if and switch statements for instance, however I would like to get some other ideas.
I've got a function with a large switch statement. This is 26 case and each with a "left" or "right" option. This function returns a pointer based on two given parameters (plane and direction):
double* getPointer(int plane, int direction) {
switch (plane)
{
case 0:
if (direction == 0)
return p_YZ_L; // Left
else if (dir == 1)
return p_YZ_R; //Right
else {
return 0;
}
break;
...
case 25:
...
}
}
with
planes -> [0-25]
direction -> [0,1]
I have been thinking on an array of functions, but this could also be tedious and I am not sure if it is the best option. Also it is not clear to me how to do it properly. Any ideas?
You can create a lookup table like this:
double *pointers[26][2] = {
{ p_YZ_L, p_YZ_R },
...
};
Then your function becomes much simpler:
double* getPointer(int plane, int direction) {
if ((plane >= 0) && (plane < 26) && (direction >= 0) && (direction < 2)) {
return pointers[plane][direction];
} else {
return NULL;
}
}
If you are just tired of typing, yu can use the preprocessor, e.g.:
#define PLZ(dir) if(!dir)return(p_YZ_L);else if(dir==1)return(p_YZ_R);else return 0;
Not quite sure, but maybe you want this:
struct
{
double dir[2];
} directions[26] =
{
{ p_YZ_L, p_YZ_R},
{ ..., ... }, // 25 pairs of options here
...
};
double* getPointer(int plane, int direction) {
return &directions[plane].dir[direction];
}
More tests need to be added to be sure that plane and direction are within required bounds.
You can use while with an iterator as follows:
double* getPointer(int plane, int direction){
int i=0;
while (i<26){
if (plane == i){
if (direction == 0)
return p_YZ_L; //Left
else if(dir==1)
return p_YZ_R; //Right
else
return 0;
}
i++;
}
}
It is not optimized but it is less code with respect to your version.

Changing the if statement into a while statement

I'm trying to change an if statement into a while statement.
For example
int A=1; if(A==1){};
is similar to int A=1 while(A!=1).
My If statement has no codes, I just need it to do nothing in order to avoid the else-if statements.
My If statement is inside 1 While statement and 1 If statement.
So I want the program to do the same thing in the while statement rather than going in 1 While statement and 1 If statement with an If statement with no code.
Original codes something like this
while(C1)
{
if(C2)
{
if( h->data[temp] < h->data[temp*2] && h->data[temp] < h->data[temp*2+1] )
{
break;
}
else if(C4)
{
DO();
}
}
}
I've changed it to
while( C1 && h->data[temp] > h->data[temp*2] && h->data[temp] > h->data[temp*2+1] )
{
if(C2)
{
if(C4)
{
DO();
}
}
}
and the result is different. The original code gives the correct result but the changed code gives an incorrect result. I've only changed the location to if to while and also changed the direction of the < operator to the > operator.
The total code seems like I've spent less effort in it, making down votes. So I'm posting the code somewhat like a pseudo code.
For example int A=1; if(A==1){}; is similar to int A=1 while(A!=1).
As already mentioned, your loop is breaking. The above statement is also incorrect.
int a = 1;
if(a == 1) {} //this is true, and will happen once
BUT
int a = 1;
while(a != 1) {} //false on entry, skip loop ( never entered )
You could also consider a switch / case if you can isolate the condition.
This might achieve your goal of removing the ifs, and make the code more readable.
e.g
int a = 1;
while(a)
{
switch(a)
{
case 1: ++a; continue;
case 2: do();
default: break; //end loop
}
}
In the original code, if (for example) h->data[temp]>h->data[temp*2] were false, DO() wouldn't be executed, but the loop would continue. In the new version, the loop would stop.
As others said, there is no reason to obfuscate the code with an extra while statement; the original is perfectly clear. There is also no need for the else in your original:
while(C1)
{
if(C2)
{
if( h->data[temp] < h->data[temp*2] && h->data[temp] < h->data[temp*2+1] )
{
break;
}
if(C4)
{
DO();
}
}
}

Is there a difference between multiple if statements and else if?

If I write
int a = 1;
int b = 2;
if (a == b) {
//Do something
} else if (a > b) {
//Do something else
} else if (a < b) {
//Do something else
}
as opposed to:
if (a == b) {
//Do something
}
if (a > b) {
//Do something else
}
if (a < b) {
//Do something else
}
Is there a difference be it the way the compiler interprets the code or speed? I see no logical difference, but there surely must be a reason why an if else statement exists. It's just a single line break difference.
In the scenario above, they are the same, other than speed. If/else will be faster than a series of ifs, because else statements are skipped if the if condition is satisfied. In a series of ifs, on the other hand, each condition is evaluated separately.
In other scenarios, of course, the logic is not the same, and so replacing if/else with a series of ifs breaks the program. Example:
// this:
if(x <= 0) {
x = 1;
}
else { // only true if x started out > 0
x = 37;
}
// is different from this:
if(x <= 0) {
x = 1;
}
if(x > 0) { // always true in this version
x = 37;
}
In else-if statements, when a condition is met, all other else-ifs are skipped.
Whereas in multiple if statements, it has to go through all of them.
To be more precise, Lets suppose a=b.
Consider your first code block:
int a = 1;
int b = 1;
if (a == b)
{
//Do something
}
else if (a > b)
{
//Do something else
}
else if (a < b)
{
//Do something else
}
While executing, since a=b, it will skip all other conditions (a>b & a<b).
Checks if a=b.
Executes the code block.
All others are skipped.
Consider your second code block:
int a = 1;
int b = 1;
if (a == b)
{
//Do something
}
if (a > b)
{
//Do something else
}
if (a < b)
{
//Do something else
}
Even the first condition is met, all of them will be evaluated.
Checks if a=b.
Executes the code block.
Checks if a>b.
Checks if a<b.
In second type of code you wrote. Compiler will show out put for each true statement and will not skip any condition. Else command is use to make sure that one of two conditions are matched.
the time complexity of if-else statements is less as compared to multiple if statements. Therefore if-else steements are much advantageous

General C program

The following code;
typedef struct chainCell{
int data;
struct chainCell* next;
} chainCell;
bool sameValues (chainCell *x, chainCell *y)
{
if ((x == NULL) & (y == NULL)) return true;
if ((x == NULL) | (y == NULL)) return false;
bool same = true;
chainCell *xp = x, *yp = y; // scan pointers
while ((xp != NULL) & (same == true)) // point A
{
if (xp->data != yp->data) same = false;
xp = xp->next;
yp = yp->next;
if (((xp == NULL) & (yp != NULL)) // point B
| ((xp != NULL) & (yp == NULL)))
same = false;
};
return same;
};
I am very confused as to why the loop control contains (same == true) ?
Also what is the purpose of the if statement at Point B? I'm unsure of what the Boolean expression is checking for?
Any help for further understanding would be appreciated!
It checks that two linked lists contain the same values.
Obviously, if one list is shorter, they are not identical (point B).
Note: I think using here break/return would be a better choice, it makes the code more readable.
Note2: as noted on the comments, those should be logical operators. It works as it is, but it's a bit confusing.
Note3: You could move the test before the loop inside the loop (while(1)), this would eliminate the need for the test at the end of the loop.
This is just an ugly code, it should be about 5 lines of code, not a dozen...
bool sameValues (chainCell *x, chainCell *y)
{
while(1) {
if (!x && !y) return true;
if (!x || !y) return false;
if (x->data != y->data) return false;
x = x->next;
y = y->next;
}
return false; //this is just to suppress compiler warning.
};
The function bool sameValues (chainCell *x, chainCell *y) checks if the two struct chainCell has the same value, that is to say, every field of chainCell type between x and y are equal.
"why the loop control contains (same == true) ?"
The boolean value same is an indicator whether the previously checked field are equal. If same == false, it is concluded that x and y are not the same in value, and the while loop could be break.
what is the purpose of the if statement at Point B?
The if statement set a condition that two fields can be equal, only if the two fields are both null or both not null.
Compact form of #Karoly Horvath's answer:
bool sameValues (chainCell *x, chainCell *y)
{
for( ; x || y; x = x->next, y = y->next) {
if (!x || !y) return false;
if (x->data != y->data) return false;
}
return true;
}
As I understand it that code is a loop to check whether two chainCell objects are the same.
(same == true) is included to cause the while loop to exit if a position in the cellChains is found where they don't match.
Point B is checking that if either of the chainCells being compared is null and the other is not null that the comparison returns false.
The exit from the loop would be caused by xp reaching a point where it is null.
I would also agree with Shafiks comment, the operators are bitwise and they should be logical.

Resources