Подтвердить что ты не робот

Проверка диапазона с помощью оператора switch

Мой учитель назначил программу для использования операторов if-else и 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;
    }
}

С помощью переключателя

#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;
    }
}

Так я думал, чтобы включить оператор switch. Есть ли способ реализовать первый блок кода только для оператора switch?

Я был почти уверен, что нельзя использовать диапазоны или использовать двойные (18.5). Я отправил письмо своему учителю, и они дали мне ответ в соответствии с

Это может не иметь смысла для вас, но иногда вам придется писать программу, которая не имеет смысла. Я не говорю, что у вас нет законных вопросов, но если кто-то может понять это, вы можете. Но тогда, может быть, это невозможно понять. Это вызов ".

Итак, я спрашиваю: есть ли какой-нибудь метод просто использовать оператор switch для первого блока кода или что я сделал лучший способ использовать оператор switch в коде, даже если он никоим образом не является необходимо?

4b9b3361

Ответ 1

Как всегда в С++, предпочитают стандартные библиотечные алгоритмы. В этом случае вы хотите выполнить поиск диапазона. Это легко с упорядоченной последовательностью границ:

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;
};

На самом деле, я предлагаю вам

Смотрите демонстрацию live на 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";
    }
}

Печать

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

Вы можете быть более элегантными без требования использовать 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));
}

Ответ 2

Если у вас нет абсолютно жуткого расширения компилятора, вы не можете switch в диапазоне на С++.

Но вы можете использовать переключатель элегантно, если вы создаете std::vector диапазонов BMI:

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

Затем используйте std::lower_bound вместе с std::distance, чтобы получить позицию данного ИМТ в указанных выше диапазонах. Это количество, на которое вы switch на.

Затем вы можете перейти на один этап и определить std::vector<std::string> выходных сообщений. Тогда вам не нужен ни блок switch, ни if! Вся логика выбора делегируется std::lower_bound.

Я намеренно не дал вам полный код: я считаю, что этих советов достаточно.

Ответ 3

Нам нужно вставить вход, поэтому вместо этого кода:

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;

    }

Вам нужно что-то вроде

switch (1 + (BMI >= 18.5) + (BMI >= 25) + (BMI >= 30) + (BMI >= 35)) {
    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;
}

Логика состоит в том, чтобы преобразовать if-elses в математическую формулу, возвращая int.

Ответ 4

Вы не можете использовать двойной переключатель внутри коммутатора. В документации указано:

switch ( expression )
   case constant-expression : statement
   [default   : statement]

Выражение должно быть целочисленного типа или типа класса для что однозначно превращается в интегральный тип. интеграл продвижение выполняется, как описано в разделе "Интеграционные акции".

На боковой ноте:

Есть несколько компиляторов (например Clang 3.5.1), которые позволяют case x ... y как расширение языка С++. Но это тоже для целостного типа данных. Что-то вроде

switch(x){
       case 0:
            cout << "Test1";
            break;
       case 0 ... 9:
            cout << "Test2";
            break;

Ответ 5

Переключатель на С++ позволяет только проверять значения целых чисел и символов.

ИМТ является двойным типом, поэтому невозможно проверить его значение в коммутаторе.

В вашем решении с коммутатором вы также должны объявить переменную BMI как двойную. Если вы объявите его как целое, все десятичные результаты будут отлиты к целому числу, и вы потеряете десятичные знаки.

Ответ 6

Вы можете рассчитывать ваши ярлыки case динамически из массива/вектора вместо hardcoding выражения if/else:

//#include "stdafx.h"
#include <iostream>

using namespace std;


inline int seg(double d){ //calculate segment for a BMI of d
  constexpr double segs[] = { 18.5, 25, 30, 35 };
  constexpr int n = sizeof(segs)/sizeof(double);
  int r; for(r=0; r<n; r++)
    if(d<segs[r]) return r;
  return r;
}

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);



  switch (seg(BMI)) {
    case 0: cout << "You are underweight" << endl; break;
    case 1: cout << "You are a normal weight " << 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;
  }

}

(Вы даже можете сделать функции seg constexpr, если это действительно нужно).

Ответ 7

Вы можете сделать что-то вроде:

switch ((round)BMI)
{
    case 1: case 2: case 3: .... case 15: case 16: case 17: cout<< "You are underweight " << endl; break;
    case 18: ... case 24: cout << "You are normal" << endl; break;
    case 25: ... case 29: cout << "You are overweight" << endl; break;
    case 30: ... case 34: cout << "You are obese" << endl; break;
    default: cout << "You are gravely overweight" << endl;
}

Также я не мог не заметить этого, так как вы используете if-else, вы можете избежать первого условия в операторах else-if, например:

if (BMI < 18.5)
{
    cout << "You are underweight " << endl;
}
else if (BMI < 25.0)
{
    cout << "You are normal" << endl;
}
else if (BMI < 30.0)
{
    cout << "You are overweight" << endl;
}
else if(BMI < 35)
{
    cout << "You are obese" << endl;
}
else
{
    cout << "You are gravely overweight" << endl;
}

Кроме того, обе ваши реализации выглядят хорошо.