all of the code listed so far has missed something: switch bounce
when you open or close a simple switch the contacts do not immediately change state and then stay there, they ‘bounce’.
If you looked at the switch on a scope it would look like a squarewave for up to 100mS.
There are two ways basic ways to debounce a switch: HW and SW.
In HW you would need to put a cap across the switch, so that the cap will charge or discharge when the switch is closed or open, and the RC time constant will absorb the bouncing. Instead of a squarewave signal you will see an exponential ramp that (with the right cap) will not cross the On and Off levels more than once. To do this correctly you really need an oscilloscope to see the waveform coming off the switch.
To debounce a switch in SW you use a SW timer. The easy way is, when you see a switch close you immediately accept that as a user input (state = closed) and do whatever you need to do (turn a motor on, turn a motor off… whatever)
but you then set a ‘debounce’ flag. You will not accept another switch closure until that debounce flag is cleared.
When you see the switch open again you decrement a debounce counter (one that will add up to 100mS or more) and you keep reading the switch on each loop. If you see the switch closed again while the debounce flag is still set, you restart the counter to its initial value (still bouncing, start the countdown over).
Once you have polled the switch for 100mS, and it stayed open each time, your debounce counter will reach 0, and you can clear the debounce flag.
This SW method gives you an instant response when you push the button, and it debounces when you take your finger off.
BTW, if you dont want to debounce your switches, the other way is to use two switches, one for ON and one for OFF. That way your outputs dont toggle while the switch is bouncing.
Edited to add: The really annoying thing about switch bounce is it happens so fast that you may not see it. If the switch bounce is toggling your output, then sometimes your system will end up in the correct state (on when you wanted on…) and randomly it will end up in the wrong state. It will act flakey, and if you dont immediately say to yourself “Ah! SwitchBounce!” it will drive you crazy trying to debug your code.