Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Range checks using a switch statement

My teacher has assigned a program to use both if-else statements and switch statements, so we understand how to implement both. The program asked us to prompt the user to input their weight and height in pounds and meters respectively. This is my attempt:

Without the switch

#include "stdafx.h" #include <iostream>  using namespace std;   int main() {     double height, weight, BMI, heightMeters, weightKilo;     const double KILOGRAMS_PER_POUND = 0.45359237;     const double METERS_PER_INCH = 0.0245;      cout << "Please enter your height (inches) and weight (pounds)" << endl;     cin >> height >> weight;      weightKilo = weight*KILOGRAMS_PER_POUND;     heightMeters = height*METERS_PER_INCH;     BMI = weightKilo / (heightMeters*heightMeters);      if (BMI < 18.5) {         cout << "You are underweight " << endl;     }     else if (BMI >= 18.5 && BMI < 25.0) {         cout << "You are normal" << endl;     }     else if (BMI >= 25.0 && BMI < 30.0) {         cout << "You are overweight" << endl;     }     else if (BMI >= 30.0 && BMI < 35) {         cout << "You are obese" << endl;     }     else {         cout << "You are gravely overweight" << endl;     } } 

With the switch

#include "stdafx.h" #include <iostream>  using namespace std;   int main() {     double height, weight, heightMeters, weightKilo;     int BMI, q;     const double KILOGRAMS_PER_POUND = 0.45359237;     const double METERS_PER_INCH = 0.0245;      cout << "Please enter your height (inches) and weight (pounds)" << endl;     cin >> height >> weight;      weightKilo = weight*KILOGRAMS_PER_POUND;     heightMeters = height*METERS_PER_INCH;     BMI = weightKilo / (heightMeters*heightMeters);      if (BMI < 18.5) {         q = 1;     }     else if (BMI >= 18.5 && BMI < 25.0) {         q = 2;     }     else if (BMI >= 25.0 && BMI < 30.0) {         q = 3;     }     else if (BMI >= 30.0 && BMI < 35) {         q = 4;     }     else {         q = 5;     }      switch (q) {         case 1: cout << "You are underweight" << endl; break;         case 2: cout << "You are a normal weight " << endl; break;         case 3: cout << "You are overweight" << endl; break;         case 4: cout << "You are obese" << endl; break;         case 5: cout << "You are gravely overweight" << endl; break;     } } 

This was the way I thought of, to include a switch statement. Is there some way to implement the first code block to just a switch statement?

I was almost certain that it could not be done to use ranges nor to use doubles (18.5). I emailed my teacher and they gave me an answer along the lines of

It may not make sense to you, but sometimes you are going to have to write a program that does not make sense. I am not saying that you don't have legitimate questions, but if anyone can figure it out you can. But then, maybe it can't be figured out. That's the challenge".

So, I'm asking: Is there some method to just use a switch statement for the first code block, or is what I did the best way to use a switch statement in the code, even if it is in no way necessary?

like image 996
TEEBQNE Avatar asked Oct 09 '15 12:10

TEEBQNE


People also ask

Can you do ranges in switch statements?

Using range in switch case in C/C++ In the switch statement we pass some value, and using different cases, we can check the value. Here we will see that we can use ranges in the case statement. After writing case, we have to put lower value, then one space, then three dots, then another space, and the higher value.

What can be checked in a switch-case statement?

Explanation: The switch/case statement in the c language is defined by the language specification to use an int value, so you can not use a float value. The value of the 'expression' in a switch-case statement must be an integer, char, short, long. Float and double are not allowed.

What are switch statements used for?

In computer programming languages, a switch statement is a type of selection control mechanism used to allow the value of a variable or expression to change the control flow of program execution via search and map.


2 Answers

As always in C++, favour standard library algorithms. In this case you want to do a range lookup. This is easy with an ordered sequence of boundaries:

double const boundaries[] = { 18.5, 25, 30, 35 };  switch (upper_bound(begin(boundaries), end(boundaries), BMI) - boundaries) {     case 0: cout << "You are underweight "       << endl; break;     case 1: cout << "You are normal"             << endl; break;     case 2: cout << "You are overweight"         << endl; break;     case 3: cout << "You are obese"              << endl; break;     case 4: cout << "You are gravely overweight" << endl; break; }; 

Actually, I suggest you

  • consider not using a switch (see BONUS section below)
  • make that a function instead of printing directly
  • drop using namespace std (see Why is "using namespace std" considered bad practice?)

See a live demo on Coliru

#include <iostream> #include <algorithm>  const char* bmi_classification(double bmi) {     static double const boundaries[] = { 18.5, 25, 30, 35 };      double const* lookup = std::upper_bound(std::begin(boundaries), std::end(boundaries), bmi);     switch (lookup - std::begin(boundaries)) {         case 0: return "underweight";         case 1: return "normal";         case 2: return "overweight";         case 3: return "obese";         case 4: return "gravely overweight";     }     throw std::logic_error("bmi_classification"); }  int main() {     for (double BMI : { 0.0, 18.4999, 18.5, 24.0, 25.0, 29.0, 30.0, 34.0, 35.0, 999999.0 }) {         std::cout << "BMI: " << BMI << " You are " << bmi_classification(BMI) << "\n";     } } 

Prints

BMI: 0 You are underweight BMI: 18.4999 You are underweight BMI: 18.5 You are normal BMI: 24 You are normal BMI: 25 You are overweight BMI: 29 You are overweight BMI: 30 You are obese BMI: 34 You are obese BMI: 35 You are gravely overweight BMI: 999999 You are gravely overweight 

BONUS

You can be more elegant without the requirement to use switch:

Live On Coliru

const char* bmi_classification(double bmi) {     constexpr int N = 5;     static constexpr std::array<char const*, N> classifications {         { "underweight", "normal", "overweight", "obese", "gravely overweight" }};     static constexpr std::array<double, N-1> ubounds {         { 18.5, 25, 30, 35 }};      auto lookup = std::upper_bound(std::begin(ubounds), std::end(ubounds), bmi);     return classifications.at(lookup - std::begin(ubounds)); } 
like image 106
sehe Avatar answered Sep 19 '22 19:09

sehe


Unless you have an absolutely ghastly compiler extension, you can't switch on a range in C++.

But you could use a switch elegantly if you create a std::vector of the BMI ranges:

std::vector<double> v = {18.5, 25.0 /*etc*/}

Then use std::lower_bound along with std::distance to get the position of a given BMI in the above ranges. This is the quantity that you switch on.

You could then go one stage further and define a std::vector<std::string> of the output messages. Then you need neither a switch nor an if block! All the selection logic is delegated to std::lower_bound.

I deliberately haven't given you the full code: I trust these hints are sufficient.

like image 24
Bathsheba Avatar answered Sep 21 '22 19:09

Bathsheba