10 - Language Switch Case

# Arduino Language Learning: Switch-Case Statements ## **🎯 What is a Switch-Case Statement?** A **Switch-Case** statement is a control structure that allows you to execute different blocks of code based on the value of a variable. Think of it like a smart traffic controller that directs different cars to different lanes based on their destination. ### **🚦 Simple Analogy** Think of switch-case like a menu at a restaurant: - **Customer orders "Pizza"** → Kitchen makes pizza - **Customer orders "Burger"** → Kitchen makes burger - **Customer orders "Salad"** → Kitchen makes salad - **Customer orders something else** → Kitchen makes default dish ### **📝 Basic Concept** Switch-case helps you: - **Replace multiple if-else statements** with cleaner code - **Handle multiple conditions** efficiently - **Make code more readable** and organized - **Execute different actions** based on a single value ## **🔧 Basic Switch-Case Syntax** ### **Simple Switch-Case Structure** ```cpp switch (variable) { case value1: // Code to execute when variable equals value1 break; case value2: // Code to execute when variable equals value2 break; default: // Code to execute when variable doesn't match any case break; } ``` ### **Complete Example** ```cpp int day = 3; switch (day) { case 1: Serial.println("Monday"); break; case 2: Serial.println("Tuesday"); break; case 3: Serial.println("Wednesday"); break; default: Serial.println("Other day"); break; } ``` ## **📊 How Switch-Case Works** ### **Step-by-Step Process** 1. **Evaluate the expression** in the switch statement 2. **Compare the result** with each case value 3. **Execute the matching case** (and all cases below it unless break is used) 4. **Execute default** if no case matches ### **Important Rules** - **Break statement**: Stops execution and exits switch - **Without break**: Execution continues to next case (fall-through) - **Default case**: Executes when no other case matches - **Case values**: Must be constants (numbers, characters, enums) ## **💡 Basic Switch-Case Examples** ### **Example 1: Simple Number Matching** ```cpp int number = 5; void setup() { Serial.begin(9600); Serial.println("Switch-Case Number Example"); } void loop() { switch (number) { case 1: Serial.println("Number is 1"); break; case 2: Serial.println("Number is 2"); break; case 3: Serial.println("Number is 3"); break; case 4: Serial.println("Number is 4"); break; case 5: Serial.println("Number is 5"); break; default: Serial.println("Number is something else"); break; } delay(2000); } ``` ### **Example 2: Character Matching** ```cpp char grade = 'B'; void setup() { Serial.begin(9600); Serial.println("Switch-Case Character Example"); } void loop() { switch (grade) { case 'A': Serial.println("Excellent!"); break; case 'B': Serial.println("Good job!"); break; case 'C': Serial.println("Average"); break; case 'D': Serial.println("Needs improvement"); break; case 'F': Serial.println("Failed"); break; default: Serial.println("Invalid grade"); break; } delay(2000); } ``` ### **Example 3: Menu System** ```cpp int menuChoice = 2; void setup() { Serial.begin(9600); Serial.println("Switch-Case Menu Example"); } void loop() { Serial.println("=== MENU ==="); Serial.println("1. Start"); Serial.println("2. Settings"); Serial.println("3. Help"); Serial.println("4. Exit"); Serial.print("Current choice: "); Serial.println(menuChoice); switch (menuChoice) { case 1: Serial.println("Starting application..."); break; case 2: Serial.println("Opening settings..."); break; case 3: Serial.println("Showing help..."); break; case 4: Serial.println("Exiting..."); break; default: Serial.println("Invalid menu choice"); break; } delay(3000); } ``` ## **🎮 Advanced Switch-Case Examples** ### **Example 1: State Machine** ```cpp enum State { IDLE, RUNNING, PAUSED, STOPPED }; State currentState = IDLE; void setup() { Serial.begin(9600); Serial.println("Switch-Case State Machine"); } void loop() { switch (currentState) { case IDLE: Serial.println("State: IDLE - Waiting for command"); currentState = RUNNING; break; case RUNNING: Serial.println("State: RUNNING - Processing data"); currentState = PAUSED; break; case PAUSED: Serial.println("State: PAUSED - Temporarily stopped"); currentState = STOPPED; break; case STOPPED: Serial.println("State: STOPPED - Process completed"); currentState = IDLE; break; default: Serial.println("State: UNKNOWN - Error state"); currentState = IDLE; break; } delay(2000); } ``` ### **Example 2: Calculator** ```cpp enum Operation { ADD, SUBTRACT, MULTIPLY, DIVIDE }; void setup() { Serial.begin(9600); Serial.println("Switch-Case Calculator"); int a = 10; int b = 5; Operation op = MULTIPLY; Serial.print(a); switch (op) { case ADD: Serial.print(" + "); Serial.print(b); Serial.print(" = "); Serial.println(a + b); break; case SUBTRACT: Serial.print(" - "); Serial.print(b); Serial.print(" = "); Serial.println(a - b); break; case MULTIPLY: Serial.print(" * "); Serial.print(b); Serial.print(" = "); Serial.println(a * b); break; case DIVIDE: Serial.print(" / "); Serial.print(b); Serial.print(" = "); Serial.println(a / b); break; default: Serial.println("Unknown operation"); break; } } void loop() { // Empty loop } ``` ### **Example 3: Error Code Handler** ```cpp enum ErrorCode { SUCCESS = 0, INVALID_INPUT = 100, NETWORK_ERROR = 200, TIMEOUT_ERROR = 300, MEMORY_ERROR = 400 }; void setup() { Serial.begin(9600); Serial.println("Switch-Case Error Handler"); ErrorCode error = NETWORK_ERROR; handleError(error); } void loop() { // Empty loop } void handleError(ErrorCode error) { switch (error) { case SUCCESS: Serial.println("Operation completed successfully"); break; case INVALID_INPUT: Serial.println("Error: Invalid input provided"); Serial.println("Action: Please check your input data"); break; case NETWORK_ERROR: Serial.println("Error: Network connection failed"); Serial.println("Action: Check your internet connection"); break; case TIMEOUT_ERROR: Serial.println("Error: Operation timed out"); Serial.println("Action: Try again later"); break; case MEMORY_ERROR: Serial.println("Error: Insufficient memory"); Serial.println("Action: Free up some memory"); break; default: Serial.println("Error: Unknown error occurred"); Serial.println("Action: Contact support"); break; } } ``` ## **🔧 Switch-Case with Functions** ### **Example 1: Function with Switch-Case** ```cpp enum Direction { NORTH, EAST, SOUTH, WEST }; void setup() { Serial.begin(9600); Serial.println("Switch-Case with Functions"); Direction dir = EAST; moveInDirection(dir); } void loop() { // Empty loop } void moveInDirection(Direction direction) { switch (direction) { case NORTH: Serial.println("Moving NORTH"); Serial.println("Action: Go forward"); break; case EAST: Serial.println("Moving EAST"); Serial.println("Action: Turn right and go forward"); break; case SOUTH: Serial.println("Moving SOUTH"); Serial.println("Action: Turn around and go forward"); break; case WEST: Serial.println("Moving WEST"); Serial.println("Action: Turn left and go forward"); break; default: Serial.println("Invalid direction"); break; } } ``` ### **Example 2: Switch-Case Returning Values** ```cpp enum Season { SPRING, SUMMER, AUTUMN, WINTER }; void setup() { Serial.begin(9600); Serial.println("Switch-Case Returning Values"); Season currentSeason = SUMMER; String seasonInfo = getSeasonInfo(currentSeason); Serial.println(seasonInfo); } void loop() { // Empty loop } String getSeasonInfo(Season season) { switch (season) { case SPRING: return "Spring: Flowers bloom, temperature rises"; case SUMMER: return "Summer: Hot weather, long days"; case AUTUMN: return "Autumn: Leaves fall, temperature drops"; case WINTER: return "Winter: Cold weather, short days"; default: return "Unknown season"; } } ``` ## **📊 Switch-Case with Arrays and Loops** ### **Example 1: Processing Array Elements** ```cpp void setup() { Serial.begin(9600); Serial.println("Switch-Case with Arrays"); int numbers[] = {1, 3, 5, 2, 4}; int size = 5; for (int i = 0; i < size; i++) { Serial.print("Processing number "); Serial.print(numbers[i]); Serial.print(": "); switch (numbers[i]) { case 1: Serial.println("One"); break; case 2: Serial.println("Two"); break; case 3: Serial.println("Three"); break; case 4: Serial.println("Four"); break; case 5: Serial.println("Five"); break; default: Serial.println("Other number"); break; } } } void loop() { // Empty loop } ``` ### **Example 2: Switch-Case in Loop with Counter** ```cpp int counter = 0; void setup() { Serial.begin(9600); Serial.println("Switch-Case in Loop"); } void loop() { int cycle = counter % 4; // Cycles through 0, 1, 2, 3 switch (cycle) { case 0: Serial.println("Cycle 0: Initialization"); break; case 1: Serial.println("Cycle 1: Processing"); break; case 2: Serial.println("Cycle 2: Verification"); break; case 3: Serial.println("Cycle 3: Completion"); break; default: Serial.println("Unexpected cycle"); break; } counter++; delay(1000); } ``` ## **⚠️ Common Mistakes and Tips** ### **Mistake 1: Missing Break Statements** ```cpp // Wrong - missing break statements switch (value) { case 1: Serial.println("One"); // Missing break! case 2: Serial.println("Two"); break; } // Result: When value is 1, both "One" and "Two" are printed // Correct - with break statements switch (value) { case 1: Serial.println("One"); break; case 2: Serial.println("Two"); break; } ``` ### **Mistake 2: Using Variables in Case Values** ```cpp // Wrong - variables in case values int x = 5; switch (value) { case x: // Error! Case values must be constants Serial.println("Five"); break; } // Correct - use constants switch (value) { case 5: Serial.println("Five"); break; } ``` ### **Mistake 3: Forgetting Default Case** ```cpp // Wrong - no default case switch (value) { case 1: Serial.println("One"); break; case 2: Serial.println("Two"); break; // What happens if value is 3, 4, 5, etc.? } // Better - with default case switch (value) { case 1: Serial.println("One"); break; case 2: Serial.println("Two"); break; default: Serial.println("Other value"); break; } ``` ### **Mistake 4: Complex Expressions in Switch** ```cpp // Wrong - complex expression switch (a + b * c) { // Avoid complex expressions case 10: Serial.println("Result is 10"); break; } // Better - simplify the expression int result = a + b * c; switch (result) { case 10: Serial.println("Result is 10"); break; } ``` ## **🎯 Best Practices** ### **1. Always Use Break Statements** ```cpp // Good - explicit break statements switch (value) { case 1: Serial.println("One"); break; case 2: Serial.println("Two"); break; default: Serial.println("Other"); break; } // Only omit break when you want fall-through behavior switch (value) { case 1: case 2: case 3: Serial.println("Small number"); break; case 4: case 5: case 6: Serial.println("Medium number"); break; } ``` ### **2. Use Default Case** ```cpp // Good - always include default switch (value) { case 1: Serial.println("One"); break; case 2: Serial.println("Two"); break; default: Serial.println("Unexpected value"); break; } ``` ### **3. Keep Cases Simple** ```cpp // Good - simple case logic switch (value) { case 1: Serial.println("One"); break; case 2: Serial.println("Two"); break; } // Avoid - complex logic in cases switch (value) { case 1: // 50 lines of complex logic break; case 2: // Another 50 lines break; } ``` ### **4. Use Enums for Better Readability** ```cpp // Good - using enums enum Color { RED, GREEN, BLUE }; Color color = GREEN; switch (color) { case RED: Serial.println("Red color"); break; case GREEN: Serial.println("Green color"); break; case BLUE: Serial.println("Blue color"); break; } // Avoid - using magic numbers int color = 1; switch (color) { case 0: Serial.println("Red color"); break; case 1: Serial.println("Green color"); break; case 2: Serial.println("Blue color"); break; } ``` ## **🚀 Advanced Switch-Case Techniques** ### **Example 1: Nested Switch-Case** ```cpp enum Category { ANIMAL, VEGETABLE, MINERAL }; enum Animal { DOG, CAT, BIRD }; void setup() { Serial.begin(9600); Serial.println("Nested Switch-Case"); Category category = ANIMAL; int subType = 1; // CAT switch (category) { case ANIMAL: Serial.println("Category: Animal"); switch (subType) { case 0: Serial.println("Subtype: Dog"); break; case 1: Serial.println("Subtype: Cat"); break; case 2: Serial.println("Subtype: Bird"); break; default: Serial.println("Unknown animal"); break; } break; case VEGETABLE: Serial.println("Category: Vegetable"); // Handle vegetable subtypes break; case MINERAL: Serial.println("Category: Mineral"); // Handle mineral subtypes break; default: Serial.println("Unknown category"); break; } } void loop() { // Empty loop } ``` ### **Example 2: Switch-Case with Range Checking** ```cpp void setup() { Serial.begin(9600); Serial.println("Switch-Case with Range Checking"); int score = 85; processScore(score); } void loop() { // Empty loop } void processScore(int score) { // Convert score to range int range = score / 10; switch (range) { case 10: case 9: Serial.println("Grade: A (Excellent)"); break; case 8: Serial.println("Grade: B (Good)"); break; case 7: Serial.println("Grade: C (Average)"); break; case 6: Serial.println("Grade: D (Below Average)"); break; default: Serial.println("Grade: F (Failed)"); break; } } ``` ### **Example 3: Switch-Case with Multiple Variables** ```cpp enum Mode { NORMAL, FAST, SLOW }; enum Direction { FORWARD, BACKWARD, LEFT, RIGHT }; void setup() { Serial.begin(9600); Serial.println("Switch-Case with Multiple Variables"); Mode mode = FAST; Direction direction = FORWARD; processMovement(mode, direction); } void loop() { // Empty loop } void processMovement(Mode mode, Direction direction) { // Combine mode and direction into a single value int action = mode * 4 + direction; switch (action) { case 0: // NORMAL + FORWARD Serial.println("Moving forward at normal speed"); break; case 1: // NORMAL + BACKWARD Serial.println("Moving backward at normal speed"); break; case 4: // FAST + FORWARD Serial.println("Moving forward at fast speed"); break; case 5: // FAST + BACKWARD Serial.println("Moving backward at fast speed"); break; case 8: // SLOW + FORWARD Serial.println("Moving forward at slow speed"); break; case 9: // SLOW + BACKWARD Serial.println("Moving backward at slow speed"); break; default: Serial.println("Unknown movement combination"); break; } } ``` ## **📚 Summary** ### **Key Points:** 1. **Switch-case** executes different code based on a variable's value 2. **Break statements** prevent fall-through to next case 3. **Default case** handles unmatched values 4. **Case values** must be constants 5. **Switch-case** is more efficient than multiple if-else statements ### **When to Use Switch-Case:** - **Multiple conditions** based on a single variable - **Menu systems** and user interfaces - **State machines** and game logic - **Error handling** with error codes - **Replacing long if-else chains** ### **Benefits:** - **More readable** than multiple if-else statements - **More efficient** execution - **Better organization** of related code - **Easier to maintain** and modify - **Clearer logic flow** ### **Next Steps:** - **Practice**: Create switch-case statements for your projects - **Experiment**: Combine with enums and functions - **Combine**: Use with loops and arrays - **Explore**: Learn about nested switch-case and advanced techniques **Switch-case statements are a powerful way to handle multiple conditions efficiently. Use them to make your Arduino code cleaner and more organized!** 🚀🔀✨