71

スイッチを使用して文字列を評価したいのですが、ユーザーが入力した文字列を読み取ると、次のエラーがスローされます。

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

エラー: タイプ 'std::string {aka std::basic_string}' からタイプ 'int へのキャストが無効です

4

7 に答える 7

91

前に述べたように、switch は整数値でのみ使用できます。したがって、「ケース」の値を整数に変換するだけです。c++11 からconstexprを使用することで実現できるため、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 
于 2013-05-05T20:06:01.240 に答える
34

文字列を列挙値にマップしてから、列挙型をオンにすることができます。

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->second;
    }
    return Option_Invalid; 
}
于 2013-05-05T20:03:53.800 に答える
19

switchステートメントは整数値にのみ使用でき、ユーザー定義型の値には使用できません。(そして、たとえそれができたとしても、入力操作も機能しません。>>操作は、空白で区切られた単一のトークンを抽出するため、値を取得することはできません"Option 1"。)

あなたはこれが欲しいかもしれません:

#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.
于 2013-05-05T19:57:17.787 に答える
15

int にキャスト可能な型に対してのみ、switch-case を使用できます。

ただし、 a を定義し、std::map<std::string, std::function> dispatcherそれを使用してdispatcher[str]()同じ効果を得ることができます。

于 2013-05-05T20:22:37.470 に答える
4

できません。完全停止。

switch使用する必要がある文字列に応じて分岐する場合は、整数型専用ですif/else

于 2013-05-05T19:57:38.603 に答える
3

オプション番号だけを持っているとどうなりますか:

#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;
}  
于 2013-05-05T20:02:50.393 に答える
1

スイッチ値は整数型でなければなりません。また、微分文字が の位置7にあることがわかっているので、 をオンにできますa.at(7)。しかし、ユーザーが 8 文字を入力したかどうかはわかりません。彼はタイプミスをしたのかもしれません。したがって、Try Catch 内で switch ステートメントを囲む必要があります。この味のあるもの

#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 ステートメントの default 句は、ユーザー入力が 8 文字以上で、{1,2,3} ではないケースをキャプチャします。

または、 で値をオンにすることもできますenum

編集

で 7 番目の文字をフェッチoperator[]()すると、境界チェックが実行されないため、動作が未定義になります。here で説明されているように、境界チェックされたat()fromを使用します。std::string

于 2013-05-05T20:05:28.557 に答える