Notifications
Clear all

switch command vs many IFs

23 Posts
3 Users
3 Likes
1,288 Views
(@tperry724)
Member
Joined: 3 years ago
Posts: 33
Topic starter  

I've never used the switch command before.  The sketch below had many IF statements and I've tried to tidy up the code.  But the sketch will not load.  I will try to post the error message below the sketch.

Best,

Tony

 

 

// simple calculator sketch


int myNumber1; //first number variable
int myNumber2; //second number variable
int result; //result variable
String calc_operator; //operator

void setup() {
// put your setup code here, to run once:
Serial.begin(115200); // begin serial monitor
}

void loop() {
// put your main code here, to run repeatedly:

Serial.print("Enter first number: "); //ask for first number
while (Serial.available()==0); //wait for the user
myNumber1=Serial.parseFloat(); //assign user entry to variable
Serial.println(myNumber1); //print user entry for reference

Serial.print("Enter second number: "); //ask for second number
while (Serial.available()==0); //wait for the user
myNumber2=Serial.parseFloat(); //assign user entry to variable
Serial.println(myNumber2); //print user entry for reference

Serial.print("Enter your operator (+,-,*,/): "); //ask user for operator
while (Serial.available()==0); //wait for the user
calc_operator=Serial.readString(); //assign user entry to string
Serial.println(calc_operator); //print user entry for reference


switch (calc_operator) {
case '+':
result = myNumber1 + myNumber2; //if addition then add
break;

case '-':
result = myNumber1 - myNumber2; //if subtraction then subtract
break;

case '*':
result = myNumber1 * myNumber2; //if multiplication then multiply
break;

case '/':
result = myNumber1 / myNumber2; //if division then divide
break;

default:
Serial.println("That was not a valid operator.");
}

Serial.print("Your answer is: "); //print message for result
Serial.println(result); //print result

Serial.println(); //tidy up with a print line

}

Arduino: 1.8.13 Hourly Build 2020/04/21 12:12 (Mac OS X), Board: "Arduino Uno"

/Users/tonyperry/Documents/Arduino/Serial_Monitor_Calculator-3/Serial_Monitor_Calculator-3.ino: In function 'void loop()':
Serial_Monitor_Calculator-3:33:22: error: switch quantity not an integer
switch (calc_operator) {
^
exit status 1
switch quantity not an integer

 

 


   
Quote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

Ah Ha, the switch only accepts integer arguments (1, 2, 3, 4). The switch cases are numbered (integers) to match the user input (1 Addition, 2 Subtraction, 3 Multiplication, 4 Division) The calc_operator variable needs to be assigned an integer value. Currently it is assigned a character value from the String.

ZoolanderMicro, where small ideas are a big deal


   
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

Your code is definitely looking better. Your use of 'while' still baffles me. It is a loop structure. Procedural code inside the loop is executed on each iteration, while the conditional statement is true. Code within an 'if' statement is executed only if the conditional statement is true. Be sure to encapsulate the procedural code in curly braces '{ }'. Below is an example program using while loops. 

 
/* Exercise_Chap05_KnightRider
  This is an exercise taken from the book:
  Beginning C for Arduino 2nd Ed (Jack Purdum)
  Knight Rider Kit car sweeping lights. This 
  version uses 'while' loops to count through
  an array of digital output pins. Notice that 
  the loop control variable is declared static 
  and initialized with a value of 0. It is shared
  between the loops in the main body of the 
  program like a game of hot potato. Also, the
  constant 'MAX_COUNT' is initialized in a way
  that scales to the index of the last array element.
  This works for different array sizes and variable types.
  Thnx Jack ;-)
  Written in Arduino C language
  @author Mike Tonge
  @date 11/26/2019
*/

// Initialize aray with Arduino digital pin numbers
int ledPins[] = {4, 5, 6, 7, 8, 9, 10};
const int DELAY_TIME = 100; // Time in milisedonds. Change to suit
const int MIN_COUNT = 0; // First aray element is index 0
// Scale value to index of last aray element // MAX_COUNT is 6
const int MAX_COUNT = (sizeof(ledPins) / sizeof(ledPins[0])) - 1; 


void setup() { 
  for (int pin = MIN_COUNT; pin <= MAX_COUNT; pin++) {
    pinMode(ledPins[pin], OUTPUT); // Initialize Arduino pins as output
    digitalWrite(ledPins[pin], LOW); // Turn digital outputs off
  }
}
void loop() {
	static int index = 0; // Initialize loop control variable.
  while (index < MAX_COUNT) { // Counts up from 0 to 5
    digitalWrite(ledPins[index], HIGH); // Turn on led
    delay(DELAY_TIME);                  // Wait a tick
    digitalWrite(ledPins[index], LOW);  // Turn off led
    index = index + 1;
  }
  while (index > MIN_COUNT) { // Counts down from 6 to 1
    digitalWrite(ledPins[index], HIGH); // Turn on led
    delay(DELAY_TIME);                  // Wait a tick
    digitalWrite(ledPins[index], LOW);  // Turn off led
    index = index - 1;
  }
}

ZoolanderMicro, where small ideas are a big deal


   
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

Here is a sketch that uses 'if' statements nested in a 'for' loop. The 'if' statements are testing for ranges of values assigned to the 'for' loop control variable 'i'. 

#include <avr/io.h>
#include <util/delay.h>
/**
   Scetch ColorFade_CommonAnode is a color fade/blend routine for a tri-color
   common anode LED connected to Arduino Uno digital pins 9, 10, and 11 as PWM
   outputs. Colors transition from blue through teal, green, yellow, orange, red,
   violet, purple, and back to blue. With common anode tri-colored LEDs,
   analogWrite() value of 0 results in a full 'on' state, and analogWrite()   
   value of 255 results in a full 'off' state.
   @author Mike Tonge
   @date 041716
*/
// Constants
const uint8_t DELAY_TIME = 100; // Delay time (miliseconds)
const uint8_t redLED = 9; // Red on digital pin 9
const uint8_t grnLED = 10; // Green on digital pin 10
const uint8_t bluLED = 11; // Blue on digital pin 11
const uint8_t OFF = 255; // Value used to turn off LED
// Variables
uint8_t redVal = 0; // Red value
uint8_t grnVal = 0; // Green value
uint8_t bluVal = 0; // Blue value
// Run once
void setup() {
  //Serial.begin(9600); // Serial monitor used for diagnostics
  pinMode(redLED, OUTPUT); // Set pin 9 as output
  pinMode(grnLED, OUTPUT); // Set pin 10 as output
  pinMode(bluLED, OUTPUT); // Set pin 11 as output
} // End setup
void loop() { // Begin 'main' loop
  for (int i = 0; i < 765; i++) { // Loop counter 'i' used to set RGB values
    // Red is off, Green gets brighter, Blue gets dimmer
    if (i <= 255) { // If 'i' is less than or equal to 255
      redVal = OFF; // Red is off
      grnVal = 255 - i; // Green brightens as 'i' increases
      bluVal = i; // Blue dims as 'i' increases
    }
    // Red gets brighter, Green gets dimmer, Blue is off
    if ((i > 255) && (i <= 510)) { // If 'i' is greater than 255 and less than or equal to 510
      redVal = 510 - i; // Red brightens as 'i' increases
      grnVal = i - 255; // Green dims as 'i' increases
      bluVal = OFF; // Blue is off
    }
    // Red gets dimmer, Green is off, Blue gets brighter
    if (i > 510) { // If 'i' is greater than 510
      redVal = i - 510; // Red dims as 'i' increases
      grnVal = OFF; // Green is off
      bluVal = 765 - i; // Blue brightens as 'i' increases
    }
    // Set RGB color values
    analogWrite(redLED, redVal);
    analogWrite(grnLED, grnVal);
    analogWrite(bluLED, bluVal);
    delay(DELAY_TIME); // Loop delay interval
    // Diagnostic output to Serial Monitor
      /**
      Serial.print(i);
      Serial.print(" , ");
      Serial.print(redVal);
      Serial.print(" , ");
      Serial.print(grnVal);
      Serial.print(" , ");
      Serial.print(bluVal);
      Serial.println();
      */
  }// End 'for' loop
}// End 'main' loop

ZoolanderMicro, where small ideas are a big deal


   
ReplyQuote
(@tperry724)
Member
Joined: 3 years ago
Posts: 33
Topic starter  

@zoolandermicro So the easiest way would be to just identify to the user the operator assigned to which number.  They enter, for instance, 1 and the case for addition would take place. Am I understanding it correctly?


   
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

Using multiple 'if' statements can be inefficient. All of the 'if' statements must be tested. Using if, else if, else statements are more efficient because the statements are tested up to the first true statement. Subsequent 'else if' statements are not considered. The trailing 'else' is usually a default to be executed when all conditions fail. 

if(test_expression)
{
   //execute your code
}
else if(test_expression n)
{
   //execute your code
}
else
{
   //execute your code
}
 

I could have used this to make the ColorFade sketch more efficient.

ZoolanderMicro, where small ideas are a big deal


   
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

I recently re-wrote the ColorFade sketch using a switch case. Switches only accept integer arguments, but they can test for ranges of numbers. This code compiled using less program memory than the previous version using 'if' statements.  

 
#include <avr/io.h>
#include <util/delay.h>
/**
   Scetch ColorBlend_CommonAnode is a color fade/blend routine for a tri-color
   common anode led connected to Arduino Uno digital pins 9, 10, and 11 as PWM
   outputs. Colors transition from blue through teal, green, yellow, orange, red,
   violet, purple, and back to blue. With common anode tri-colored LEDs,
   analogWrite() value of 0 results in a full 'on' state, and analogWrite()   
   value of 255 results in a full 'off' state. This scetch works with common
   cathode tri-colored leds, only the color blend runs in the opposite order.
   Written in Arduino C language.
   @author Mike Tonge
   @date 11/28/2019
*/
// Constants
const uint8_t DELAY_TIME = 100; // Delay time (miliseconds)
const uint8_t redLED = 9; // Red on digital pin 9
const uint8_t grnLED = 10; // Green on digital pin 10
const uint8_t bluLED = 11; // Blue on digital pin 11
const uint8_t OFF = 255; // Value used to turn led off
// Variables
uint8_t redVal = 0; // Red value
uint8_t grnVal = 0; // Green value
uint8_t bluVal = 0; // Blue value

void setup() {
  pinMode(redLED, OUTPUT); // Set pin 9 as output
  pinMode(grnLED, OUTPUT); // Set pin 10 as output
  pinMode(bluLED, OUTPUT); // Set pin 11 as output
}

void loop() {
  for (int count = 0; count <= 765; count++) {
    switch (count) {
      // Red is off, Green gets brighter, Blue gets dimmer
      case 0 ... 255:
        redVal = OFF;
        grnVal = 255 - count;
        bluVal = count;
        break;
      // Red gets brighter, Green gets dimmer, Blue is off
      case 256 ... 510:
        redVal = 510 - count;
        grnVal = count - 255;
        bluVal = OFF;
        break;
      // Red gets dimmer, Green is off, Blue gets brighter
      case 511 ... 765:
        redVal = count - 510;
        grnVal = OFF;
        bluVal = 765 - count;
        break;
      default:
        break;
    } // End switch
    analogWrite(redLED, redVal);
    analogWrite(grnLED, grnVal);
    analogWrite(bluLED, bluVal);
    delay(DELAY_TIME);
  }
}

ZoolanderMicro, where small ideas are a big deal


   
tperry724 reacted
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

Yes, the user enters a number for the intended operation. I'm trying to find a sketch that accepts user input as an example. 

ZoolanderMicro, where small ideas are a big deal


   
ReplyQuote
(@tperry724)
Member
Joined: 3 years ago
Posts: 33
Topic starter  

@zoolandermicro - Thank you for all of your guidance.  I'd like to build and try the color fad sketch in the near future.


   
ReplyQuote
frogandtoad
(@frogandtoad)
Member
Joined: 5 years ago
Posts: 1458
 

@tperry724

 // Change this variable to be of type "char"
 char calc_operator;

 // Change from "readString()" to "read()" a single character
 calc_operator = Serial.read();

You were trying to switch on a string data type instead of an int type, which char is.

Cheers.


   
ReplyQuote
frogandtoad
(@frogandtoad)
Member
Joined: 5 years ago
Posts: 1458
 

@zoolandermicro

Posted by: @zoolandermicro

Ah Ha, the switch only accepts integer arguments (1, 2, 3, 4). The switch cases are numbered (integers) to match the user input (1 Addition, 2 Subtraction, 3 Multiplication, 4 Division) The calc_operator variable needs to be assigned an integer value. Currently it is assigned a character value from the String.

I hope you don't mind me correcting you, but this needs a little clarification.

The data type char is also an integral type, which maps to associated ASCII characters, and that's why we can also switch on a character literal, as well as an explicit number.

For example:

int character = '+';
  Serial.println(character);       // Correctly prints ASCII integer 43
  Serial.println(char(character)); // Convert from int back to char representation '+'

Cheers.


   
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

Excellent! Thanks FrogandToad, I have not tried that before. Could Tperry724 use this to accept user input of arithmetic symbols (+, -, *, /)? 

switch (calc_operator) {
case '+':
result = myNumber1 + myNumber2; //if addition then add
break;

case '-':
result = myNumber1 - myNumber2; //if subtraction then subtract
break;

case '*':
result = myNumber1 * myNumber2; //if multiplication then multiply
break;

case '/':
result = myNumber1 / myNumber2; //if division then divide
break;

default:
Serial.println("That was not a valid operator.");
}

ZoolanderMicro, where small ideas are a big deal


   
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

For the case statements, should he still use single quotes for a character? I wouldn't think so.

ZoolanderMicro, where small ideas are a big deal


   
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

As in:

switch (calc_operator) {
case 43: // ASCII for + symbol
result = myNumber1 + myNumber2; //if addition then add
break;

case  45: // ASCII for - symbol
result = myNumber1 - myNumber2; //if subtraction then subtract
break;

case  42: // ASCII for * symbol
result = myNumber1 * myNumber2; //if multiplication then multiply
break;

case  47: //ASCII for / symbol
result = myNumber1 / myNumber2; //if division then divide
break;

default:
Serial.println("That was not a valid operator.");
}

ZoolanderMicro, where small ideas are a big deal


   
ReplyQuote
ZoolanderMicro
(@zoolandermicro)
Member
Joined: 4 years ago
Posts: 144
 

When I reply with a preformatted code block, I don't seem to be able to add text afterward. Do I just add text after the closing </pre> tag in the code block dialog? 

ZoolanderMicro, where small ideas are a big deal


   
ReplyQuote
Page 1 / 2