Author Topic: Give me a Clue About if Statements  (Read 967 times)

0 Members and 1 Guest are viewing this topic.

Offline Roy Batty

  • Regular Contributor
  • *
  • Posts: 51
  • Country: us
Give me a Clue About if Statements
« on: January 11, 2017, 12:21:30 PM »
Maybe I should put this question on a programming forum, but I thought I'd give it a shot here. Sorry if it's out of place.

I am working on Arduino programming, and I've been dealing with if statements. I have a very basic question.

Let's say I have some value I'm reading. It's an int, and I'll call it "OnOff." Suppose it tells you whether a light is on or off. If it's on, you want to do something. If it's off, you want to do something else.

You write an if statement. The statement has to reflect the fact that you've changed the system, so it has to change the value of "OnOff" before it's over.

So you have something like:

if (something or other) {
   if (OnOff == 0) {
        OnOff = 1;
        ______;
        ______;
                           }

   if (OnOff == 1_ {
       OnOff = 0;
       ______;
       ______;
                         }
   }

The idea is that you do one thing if OnOff is 0, and you do something else if OnOff is 1, and then you change the value of OnOff in order to reflect that something has been done.

The question is this: will the second half of the if statement above read the change in OnOff (made in the first half) before running? You want the top part (not the bottom part) to run if OnOff is 0, so you would not want the bottom part to read the bit where OnOff is changed to 1 and start running.
 

Online hendorog

  • Frequent Contributor
  • **
  • Posts: 561
  • Country: nz
Re: Give me a Clue About if Statements
« Reply #1 on: January 11, 2017, 12:33:03 PM »
One way is to use an 'else' in front of the second 'if'.
If OnOff will only ever be 0 or 1 then you can just use 'else' on its own and remove 'if (OnOff ==1)'

Code: [Select]
if (something or other) {
   if (OnOff == 0) {
        OnOff = 1;
        ______;
        ______;
   } else if (OnOff == 1) {
       OnOff = 0;
       ______;
       ______;
   }
}
 
The following users thanked this post: BillyD

Offline ChristofferB

  • Frequent Contributor
  • **
  • Posts: 298
  • Country: dk
    • My blog:
Re: Give me a Clue About if Statements
« Reply #2 on: January 11, 2017, 12:34:44 PM »
Another way is to use the 'switch' statement. If I recall correctly, it ends if the condition of a level of the switch is true.
--Christoffer

I know what a look up table is, but I can't help but imagining it being something you yell to a guy who's about to get hit by falling furniture.
 

Offline Mr.B

  • Frequent Contributor
  • **
  • Posts: 711
  • Country: nz
Re: Give me a Clue About if Statements
« Reply #3 on: January 11, 2017, 12:41:34 PM »
There are multiple ways to skin that cat.
My way would be as follows and I would also declare OnOff as a boolean rather than an int
Code: [Select]
if (something or other) {
   if (OnOff) {
        OnOff = false;
        ______;
        ______;
   } else {
       OnOff = true;
       ______;
       ______;
   }
}
Time is the overseer of all things.
 

Online iaeen

  • Contributor
  • Posts: 44
  • Country: us
Re: Give me a Clue About if Statements
« Reply #4 on: January 11, 2017, 01:10:25 PM »
Another way is to use the 'switch' statement. If I recall correctly, it ends if the condition of a level of the switch is true.

My C us unfortunately rusty, but I believe you have to manually break out of a switch. That would work for the OP since none of the other conditions matter after the break:
Code: [Select]
Switch{
    Case OnOff;
        OnOff=0;
        //other stuff goes here
    Break;
    Case !OnOff;
        OnOff=1;
        //again with the other stuff
    Break;
}

Without the breaks, you would execute all the code in the switch starting with the first case that evaluates true. For example:
Code: [Select]
Switch {
    Case true;
        foo="this won't be the final value of the variable";
    Case false;
        foo="This is will be the final value";
}

I'd still probably use an if/else statement. Most people only use switches if there are a bunch of cases.
« Last Edit: January 11, 2017, 01:22:20 PM by iaeen »
 

Offline Roy Batty

  • Regular Contributor
  • *
  • Posts: 51
  • Country: us
Re: Give me a Clue About if Statements
« Reply #5 on: January 11, 2017, 02:17:51 PM »
Thanks, all. I just want to know for sure: will it read and execute the second part of the statement even after reading and executing the second part? I'm not concerned about finding a way around it, because using "else" seems to work.

I just assumed that if you put two "if" statements in series, intending to have a disjunction, the computer would only read one, but I guess that's not true. I guess the first if has no effect on the second, and "else" really means, "If that didn't work, try this."
 

Offline Mr.B

  • Frequent Contributor
  • **
  • Posts: 711
  • Country: nz
Re: Give me a Clue About if Statements
« Reply #6 on: January 11, 2017, 02:25:27 PM »
In your original code, the second statement would always get executed if the first statement was executed.
This is because the first statement would set the OnOff variable to a value that evaluates to True in the second test.
Time is the overseer of all things.
 

Offline donotdespisethesnake

  • Frequent Contributor
  • **
  • Posts: 316
  • Country: gb
  • Embedded stuff
Re: Give me a Clue About if Statements
« Reply #7 on: January 11, 2017, 10:13:10 PM »
OnOff is a terrible name of course. LightOn would be much better, and make it a bool.
Bob
 
The following users thanked this post: HackedFridgeMagnet

Offline MattHollands

  • Regular Contributor
  • *
  • Posts: 165
  • Country: 00
    • Matt's Projects
Re: Give me a Clue About if Statements
« Reply #8 on: January 12, 2017, 12:31:55 AM »
Thanks, all. I just want to know for sure: will it read and execute the second part of the statement even after reading and executing the second part? I'm not concerned about finding a way around it, because using "else" seems to work.

I just assumed that if you put two "if" statements in series, intending to have a disjunction, the computer would only read one, but I guess that's not true. I guess the first if has no effect on the second, and "else" really means, "If that didn't work, try this."

The computer is dumb and everything is sequential. First the computer looks at the first if-statement and evaluates it. When it's done with the first if-statement, it completely forgets about it. Then it looks at the second if statement - it doesn't think "ah I've already evaluated this variable in this loop, I'll ignore this" - it does exactly as it is told and evaluates the second if statement.

If you put 1 million exactly the same if-statements in a row, it would evaluate them all.

(Yes, compiler optimisation may break some of these rules - but there are very rare occasions when you will need to worry about this).

Basically for a variable with two values I would use:

Code: [Select]
if (something or other)
{
   if (OnOff == 0) {
        OnOff = 1;
        ______;
        ______;
    }
    else
    {
       OnOff = 0;
       ______;
       ______;
   }
}


(also as mentioned before I would prefer to use a bool than an int)
« Last Edit: January 12, 2017, 12:41:14 AM by MattHollands »
Read about my stuff at: projects.matthollands.com
 

Offline Roy Batty

  • Regular Contributor
  • *
  • Posts: 51
  • Country: us
Re: Give me a Clue About if Statements
« Reply #9 on: January 12, 2017, 04:15:54 AM »
My flashing LED's are working very nicely now. It's an exciting day in the history of computer science.
 

Offline AndyC_772

  • Super Contributor
  • ***
  • Posts: 2627
  • Country: gb
  • Will design for cookies
Re: Give me a Clue About if Statements
« Reply #10 on: January 12, 2017, 04:27:45 AM »
You might enjoy VHDL; logic is evaluated very differently.

For example:

Code: [Select]
IF rising_edge (clk) THEN
  IF LightOn = '1' THEN
    LightOn <= '0';
    ...do some stuff...
  END IF;

  IF LightOn = '0' THEN
    LightOn <= '1';
    ...do other stuff...
  END IF;
END IF;

... actually does work how you'd hope it might, rather than how a programmer more familiar with languages like C (and the various mistakes that beginners often make) would expect it to.
 

Online rstofer

  • Super Contributor
  • ***
  • Posts: 1663
  • Country: us
Re: Give me a Clue About if Statements
« Reply #11 on: January 12, 2017, 04:28:23 AM »
There is a school of thought that conditionals like OnOff == 0 are evil.  Here's why...

When you write
Code: [Select]
if (OnOff == 0)
it sometimes happens that you actually type
Code: [Select]
if (OnOff = 0)
which unconditionally sets OnOff to 0 and the expression evaluates to false.  This kind of thing is surprisingly hard to debug and happens far more often than you would think.

So, the idea is to turn the expression around
Code: [Select]
if (0 == OnOff)   // this will compile and work properly
whereas
Code: [Select]
if (0=OnOff) // this won't even compile

I am trying to retrain myself to use the alternate expression.  I wish I could say it is working...
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 3336
Re: Give me a Clue About if Statements
« Reply #12 on: January 12, 2017, 04:37:23 AM »
If its a boolean value then simply use either
Code: [Select]
if(OnOff) // test if TRUEor
Code: [Select]
if(!OnOff) // test if FALSEThe == doesn't add any clarity, is more verbose and increases the risk of a typo resulting in an = assignment.
   
 

Offline djacobow

  • Frequent Contributor
  • **
  • Posts: 542
  • Country: us
  • takin' it apart since the 70's
Re: Give me a Clue About if Statements
« Reply #13 on: January 12, 2017, 04:57:44 AM »
If its a boolean value then simply use either
Code: [Select]
if(OnOff) // test if TRUEor
Code: [Select]
if(!OnOff) // test if FALSEThe == doesn't add any clarity, is more verbose and increases the risk of a typo resulting in an = assignment.
 

This is idiomatic c and you should code this way as long as the type can be interpreted as a boolean, regardless of what type it actually is. Code like:


if (a == 0) { }


give me the shakes, and


int *p;
...
if (p == NULL) { }


causes seizures.

Don't do it! :-)
 

Offline hamster_nz

  • Frequent Contributor
  • **
  • Posts: 936
  • Country: nz
Re: Give me a Clue About if Statements
« Reply #14 on: January 12, 2017, 07:20:44 AM »
If its a boolean value then simply use either
Code: [Select]
if(OnOff) // test if TRUEor
Code: [Select]
if(!OnOff) // test if FALSEThe == doesn't add any clarity, is more verbose and increases the risk of a typo resulting in an = assignment.
 

This is idiomatic c and you should code this way as long as the type can be interpreted as a boolean, regardless of what type it actually is. Code like:


if (a == 0) { }


give me the shakes, and


int *p;
...
if (p == NULL) { }


causes seizures.

Don't do it! :-)

A quick puzzle - what is wrong with this:

Code: [Select]
  int f;
  if(!(f = open("file",O_RDONLY))) {
     fatal_error("Unable to open 'file'");
  }


with that in mind, which do you hate more, and why...

Option A
Code: [Select]
  FILE *f;
  f = fopen("file","rb");
  if(f == NULL) {
     fatal_error("Unable to open 'file'");
  }

vs

Option B
Code: [Select]
  FILE *f;
  f = fopen("file","rb");
  if(!f) {
     fatal_error("Unable to open 'file'");
  }

vs

Option C
Code: [Select]
  FILE *f;
  if(!(f = fopen("file","rb"))) {
     fatal_error("Unable to open 'file'");
  }

vs (some insane Perl inspired crap...)

Option D
Code: [Select]
  FILE *f;
  (f = fopen("file","rb")) || fatal_error("Unable to open 'file'");

I prefer the first, because I like the "try something. Did it return an error? If so handle the exception" pattern.

EDIT: Actually tested code and fixed dumb syntax errors :)
« Last Edit: January 12, 2017, 08:24:00 AM by hamster_nz »
 

Offline MarkL

  • Supporter
  • ****
  • Posts: 956
  • Country: us
Re: Give me a Clue About if Statements
« Reply #15 on: January 12, 2017, 07:52:28 AM »
If you're using GCC, I would suggest you always compile with "-Wall -Werror" (or some reasonable subset of warning options if "all" is too picky for you).

Then, code like this with unintended assignments:
Code: [Select]
#include <stdio.h>

int main()
{
    int a;
    int *p;

    if (a = 0) { }
    if (p = NULL) { }

    return 0;
}
will result in warning messages and stop the compilation, like so:

Code: [Select]
zz.c: In function ‘main’:
zz.c:8: warning: suggest parentheses around assignment used as truth value
zz.c:9: warning: suggest parentheses around assignment used as truth value
 

Offline Roy Batty

  • Regular Contributor
  • *
  • Posts: 51
  • Country: us
Re: Give me a Clue About if Statements
« Reply #16 on: January 12, 2017, 09:44:35 AM »
This thread has been over my head since some time yesterday.
 

Offline MarkL

  • Supporter
  • ****
  • Posts: 956
  • Country: us
Re: Give me a Clue About if Statements
« Reply #17 on: January 12, 2017, 10:44:02 AM »
My apologies for the off-topic post.  henderog had the answer in the first reply to your post.  Use an "else".
 

Offline Kremmen

  • Super Contributor
  • ***
  • Posts: 1241
  • Country: fi
Re: Give me a Clue About if Statements
« Reply #18 on: January 12, 2017, 11:30:08 AM »
The discussion went off on a tangent as always happens. But from the already given answers to the original question, do take home a couple of good bits:
- learn to use the boolean type (name of boolean type is 'bool' in Arduino) for variables that are only meaningful as 'on'/'off' or true/false. A boolean can have just those 2 values and that will spare you all kinds of stupid errors later. What if your OnOff accidentally gets a value 3 and you always compare to 0 or 1? Can't happen with a boolean type.
- Name Booleans to indicate the true case. So don't do GizmoOnOff, but do gizmoOn.
- Then compare against the true value: if ( gizmoOn ) ... Self evident don't you think. In rare cases compare against the inverted value: if ( !gizmoOn ) ... (i.e. if gizmo off...)

Now that i got going, other similar pieces of sagely advice:
- do not embed magic numbers in your code. Two weeks after writing a piece of software you will not recall what all the numbers meant again, that you have sprinkled around the code. Instead do #define your magick numbers as named constants thus:
#define MAX_GIZMOS 10
#define PULSE_DELAY 10
etc.
In the code you use the #defined names: if ( numberOfActualGizmos >= MAXGIZMOS ) alarm();
Now when you later want to increase the maximum number of gizmos to 11, you just change the #define instead of hunt all over the code for just those 10's that are related to amount of gizmos.

- another very useful practice is to learn to use enumerated types. Sounds cryptic but isn't and helps the compiler to report certain kinds of error not easily spotted otherwise. Not to mention that it makes life easier for you the programmer.
Enumerated type are very useful when you hvae a small number of exclusive distinct values and other values don't make sense. A classic example is how to identify e.g. colors. You could assign 1 to red, 2 to blue and so on. But later in your code how will you recall what number was which color? You could #define the values sure, but easier to just declare 'enum color {red, blue, green yellow cyan, magenta};' That way the compiler remembers the values for you, and you just call the colors by name. Now you can declare variable to be of type 'color': color background; color foreground; etc. Later just say e.g. 'background = blue;' to assign bg color.

I wish to God these calculations had been executed by steam!
C. Babbage
 

Offline djacobow

  • Frequent Contributor
  • **
  • Posts: 542
  • Country: us
  • takin' it apart since the 70's
Re: Give me a Clue About if Statements
« Reply #19 on: January 12, 2017, 11:32:30 AM »

with that in mind, which do you hate more, and why...


I liked B the best, but prefer


FILE *f = fopen("some.file","rb");
if (!f) {
  ...
}


I guess I can't justify it with any hard rule. I think combining declaration and assignment is a good use of vertical space, but putting assignment in a conditional is not.

NULL, though, bothers me. It's usually just a macro for (void *)0. The C standard makes it clear that the value 0 in a pointer context (even without the cast to void*) is a null pointer. So, though, from a hardware perspective, one could have a pointer that is not null that points to memory location 0, the C language is not part of that universe -- thus stealing a precious byte of usable address space from us but sparing us from having to look at NULL and all its many homebrew nonsense variants.

I'm not even sure what work the (void *) cast is doing in the macro definition of NULL. At first, I thought it  was so that you would get a warning or error if you tried to assign NULL to something that is not a pointer. But, nope, that works just fine, too.

 

Offline djacobow

  • Frequent Contributor
  • **
  • Posts: 542
  • Country: us
  • takin' it apart since the 70's
Re: Give me a Clue About if Statements
« Reply #20 on: January 12, 2017, 11:43:19 AM »
The discussion went off on a tangent as always happens. But from the already given answers to the original question, do take home a couple of good bits:
- learn to use the boolean type (name of boolean type is 'bool' in Arduino) for variables that are only meaningful as 'on'/'off' or true/false. A boolean can have just those 2 values and that will spare you all kinds of stupid errors later.

Sorry, I thought tangents were fun?

I am just chiming in again to say that the original question was about "C", which until C99 had no boolean type, though you could use any integer type and it works just like a bool as long as you only do booly stuff to it.

I'm not certain what problem C99's stdbool.h is solving, but I guess the world got tired of seeing some variation of

typedef enum { false, true } bool;

in everyone's code. I guess they could also be wanting to harmonize with C++.



 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 3336
Re: Give me a Clue About if Statements
« Reply #21 on: January 12, 2017, 12:52:19 PM »
I am just chiming in again to say that the original question was about "C", which until C99 had no boolean type, though you could use any integer type and it works just like a bool as long as you only do booly stuff to it.
I started the bool branch of the tangent, but in my defence I said "boolean values" which can be stored in any K&R or C89 integer typed variable, and didn't mention the C99 'bool' boolean type.
 

Offline boffin

  • Supporter
  • ****
  • Posts: 300
  • Country: ca
Re: Give me a Clue About if Statements
« Reply #22 on: January 12, 2017, 01:04:35 PM »
Maybe I should put this question on a programming forum, but I thought I'd give it a shot here. Sorry if it's out of place.

I am working on Arduino programming, and I've been dealing with if statements. I have a very basic question.

Let's say I have some value I'm reading. It's an int, and I'll call it "OnOff." Suppose it tells you whether a light is on or off. If it's on, you want to do something. If it's off, you want to do something else.

You write an if statement. The statement has to reflect the fact that you've changed the system, so it has to change the value of "OnOff" before it's over.

So you have something like:

if (something or other) {
   if (OnOff == 0) {
        OnOff = 1;
        ______;
        ______;
                           }

   if (OnOff == 1_ {
       OnOff = 0;
       ______;
       ______;
                         }
   }

The idea is that you do one thing if OnOff is 0, and you do something else if OnOff is 1, and then you change the value of OnOff in order to reflect that something has been done.

The question is this: will the second half of the if statement above read the change in OnOff (made in the first half) before running? You want the top part (not the bottom part) to run if OnOff is 0, so you would not want the bottom part to read the bit where OnOff is changed to 1 and start running.
Yes, which is why there are else statements. What you're looking for is

Code: [Select]
if (something or other) {
   if (OnOff == 0) {
        OnOff = 1;
        ______;
        ______;
   }
   else {               // this block runs if the above block didn't
       OnOff = 0;
       ______;
       ______;
   }
}

 

Offline Kremmen

  • Super Contributor
  • ***
  • Posts: 1241
  • Country: fi
Re: Give me a Clue About if Statements
« Reply #23 on: January 12, 2017, 07:24:02 PM »
[...]
Sorry, I thought tangents were fun?

I am just chiming in again to say that the original question was about "C", which until C99 had no boolean type, though you could use any integer type and it works just like a bool as long as you only do booly stuff to it.

I'm not certain what problem C99's stdbool.h is solving, but I guess the world got tired of seeing some variation of

typedef enum { false, true } bool;

in everyone's code. I guess they could also be wanting to harmonize with C++.

Oh, i didn't say tangents can't be fun. No problem there - it was jus an observation of how things usually go.

I confess being one of those who has gotten deadly tired of seeing all possible permutations of the way in which the enumeration of {false, true} can be expressed and fail to be compatible with any of the others. But that was not the point. Instead the point was just to illuminate the whole concept of using variables as something other than numbers or strings of characters.
I wish to God these calculations had been executed by steam!
C. Babbage
 

Offline T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 7298
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: Give me a Clue About if Statements
« Reply #24 on: January 13, 2017, 01:57:08 AM »
Note that you can put the assignment of OnOff outside the inner if statement.  That is,

Code: [Select]
if (something) {
    OnOff = !OnOff // use a bool type for semantic correctness
    if (OnOff) {
        // OnOff was off and now it's on. Do the "off" stuff.
    } else {
        // OnOff was on and now it's off. Do the "on" stuff.
    }
}

But this is confusing, because the inner if statement is upside-down so to speak.  We can simply defer changing OnOff to later,

Code: [Select]
if (something) {
    if (OnOff) {
        // OnOff is on. Do the "on" stuff.
    } else {
        // OnOff is off. Do the "off" stuff.
    }
    OnOff = !OnOff
}

This is fine, but isn't foolproof: a pathological case could have a break or goto inside the if statement, which gleefully leaves before the OnOff assignment is evaluated.  Simple enough: don't use goto, and use break only when appropriate (most often in switch statements, or when you need to exit a for or while statement prematurely).



An aside: switch statements are quite inefficient until you need a large list of consecutive options (ten or more, say).  Nothing wrong with the semantics -- it's just slow and bulky until you need a lot of options.

Tim
Seven Transistor Labs, LLC
Electronic Design, from Concept to Layout.
Need engineering assistance? Drop me a message!
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf