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

Оценить строку с помощью переключателя на С++

Я хочу оценить строку с помощью переключателя, но когда я прочитал строку, введенную пользователем, я нахожу следующую ошибку.

#include<iostream>
using namespace std;

    int main() {
        string a;
        cin>>a;
        switch (string(a)) {
        case "Option 1":
            cout<<"It pressed number 1"<<endl;
            break;
        case "Option 2":
            cout<<"It pressed number 2"<<endl;
            break;
        case "Option 3":
            cout<<"It pressed number 3"<<endl;
            break;
        default:
            cout<<"She put no choice"<<endl;
            break;
        }
        return 0;
    }

error: неверный листинг из типа 'std::string {aka std:: basic_string}' для ввода 'int

4b9b3361

Ответ 1

Как уже говорилось, коммутатор может использоваться только с целыми значениями. Таким образом, вам просто нужно преобразовать ваши значения "case" в integer. Вы можете достичь этого, используя constexpr из С++ 11, поэтому некоторые вызовы функций constexpr можно вычислить во время компиляции.

что-то вроде этого...

switch (str2int(s))
{
  case str2int("Value1"):
    break;
  case str2int("Value2"):
    break;
}

где str2int похож (реализация из здесь):

constexpr unsigned int str2int(const char* str, int h = 0)
{
    return !str[h] ? 5381 : (str2int(str, h+1) * 33) ^ str[h];
}

Другой пример: следующая функция может быть вычислена во время компиляции:

constexpr int factorial(int n)
{
    return n <= 1 ? 1 : (n * factorial(n-1));
}  

int f5{factorial(5)};
// Compiler will run factorial(5) 
// and f5 will be initialized by this value. 
// so programm instead of wasting time for running function, 
// just will put the precalculated constant to f5 

Ответ 2

Оператор

A switch может использоваться только для целых значений, а не для значений пользовательского типа. И даже если это возможно, ваша операция ввода также не работает.

Вам может понадобиться следующее:

#include <string>
#include <iostream>


std::string input;

if (!std::getline(std::cin, input)) { /* error, abort! */ }

if (input == "Option 1")
{
    // ... 
}
else if (input == "Option 2")
{ 
   // ...
}

// etc.

Ответ 3

Вы можете использовать только тип switch-case для типов, применимых к int.

Однако вы можете определить std::map<std::string, std::function> dispatcher и использовать его как dispatcher[str]() для достижения такого же эффекта.

Ответ 4

Вы можете сопоставить строки с значениями перечисления, затем включить перечисление:

enum Options {
    Option_Invalid,
    Option1,
    Option2,
    //others...
};

Options resolveOption(string input);

//  ...later...

switch( resolveOption(input) )
{
    case Option1: {
        //...
        break;
    }
    case Option2: {
        //...
        break;
    }
    // handles Option_Invalid and any other missing/unmapped cases
    default: {
        //...
        break;
    }
}

Разрешение перечисления может быть реализовано как серия проверок if:

 Options resolveOption(std::string input) {
    if( input == "option1" ) return Option1;
    if( input == "option2" ) return Option2;
    //...
    return Option_Invalid;
 }

Или поиск карты:

 Options resolveOption(std::string input) {
    static const std::map<std::string, Option> optionStrings {
        { "option1", Option1 },
        { "option2", Option2 },
        //...
    };

    auto itr = optionStrings.find(input);
    if( itr != optionStrings.end() ) {
        return *itr;
    }
    return Option_Invalid; 
}

Ответ 5

а как же просто номер опции:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s;
    int op;

    cin >> s >> op;
    switch (op) {
    case 1: break;
    case 2: break;
    default:
    }

    return 0;
}  

Ответ 6

Вы не можете. Полная остановка.

switch предназначен только для целых типов, если вы хотите разветкиться в зависимости от строки, которую вы должны использовать if/else.

Ответ 7

Значение переключателя должно иметь тип Integral. Кроме того, поскольку вы знаете, что дифференцирующий символ находится в положении 7, вы можете включить a.at(7). Но вы не уверены, что пользователь ввел 8 символов. Возможно, он допустил ошибку ввода. Поэтому вы должны окружить свой оператор switch в Try Catch. Что-то с этим ароматом

#include<iostream>
using namespace std;
int main() {
    string a;
    cin>>a;

    try
    {
    switch (a.at(7)) {
    case '1':
        cout<<"It pressed number 1"<<endl;
        break;
    case '2':
        cout<<"It pressed number 2"<<endl;
        break;
    case '3':
        cout<<"It pressed number 3"<<endl;
        break;
    default:
        cout<<"She put no choice"<<endl;
        break;
    }
    catch(...)
    {

    }
    }
    return 0;
}

Предложение по умолчанию в инструкции switch фиксирует случаи, когда пользователь вводит не менее 8 символов, но не в {1,2,3}.

В качестве альтернативы вы можете включить значения в enum.

ИЗМЕНИТЬ

Извлечение 7-го символа с помощью operator[]() не выполняет проверку границ, поэтому поведение будет undefined. мы используем at() из std::string, который проверяется границами, как описано здесь.