如何在switch语句中选择一系列值?

时间:2012-02-24 14:19:05

标签: c++ switch-statement

当我尝试编译时,我收到此错误:

1>------ Build started: Project: snake, Configuration: Debug Win32 ------
1>  exercise.cpp
1>c:\users\robin\documents\visual studio 2010\projects\snake\snake\exercise.cpp(13): error C2059: syntax error : '>='
1>c:\users\robin\documents\visual studio 2010\projects\snake\snake\exercise.cpp(16): error C2059: syntax error : '>='
1>c:\users\robin\documents\visual studio 2010\projects\snake\snake\exercise.cpp(19): error C2059: syntax error : '>='
1>c:\users\robin\documents\visual studio 2010\projects\snake\snake\exercise.cpp(22): error C2059: syntax error : '>='
1>c:\users\robin\documents\visual studio 2010\projects\snake\snake\exercise.cpp(25): error C2059: syntax error : '>'
1>c:\users\robin\documents\visual studio 2010\projects\snake\snake\exercise.cpp(28): error C2059: syntax error : '=='
1>c:\users\robin\documents\visual studio 2010\projects\snake\snake\exercise.cpp(34): warning C4065: switch statement contains 'default' but no 'case' labels
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

代码:

#include <iostream>
using namespace std;

int main(){
    int score;

    //Vraag de score
    cout << "Score:";
    cin >> score;

    //Switch
    switch(score){
        case >= 100:
            cout << "a";
            break;
        case >= 50:
            cout << "b";
            break;
        case >= 25:
            cout << "c";
            break;
        case >= 10:
            cout << "d";
            break;
        case > 0:
            cout << "e";
            break;
        case == 0:
            cout << "f";
            break;
        default:
            cout << "BAD VALUE";
            break;
    }
    cout << endl;
    return 0;
}

如何解决此问题?它是一个控制台应用程序,Win32和我的IDE是Windows Enterprise C ++ 2010。

我正在学习通过游戏编程开始C ++

18 个答案:

答案 0 :(得分:50)

某些编译器支持案例范围,例如case x ... y作为C ++语言的扩展

示例:

#include <iostream>
using namespace std;

int main(){
    int score;

    //Vraag de score
    cout << "Score:";
    cin >> score;

    //Switch
    switch(score){
       case 0:
            cout << "a";
            break;
       case 0 ... 9:
            cout << "b";
            break;
       case 11 ... 24:
            cout << "c";
            break;
       case 25 ... 49:
            cout << "d";
            break;
       case 50 ... 100:
            cout << "e";
            break;         
        default:
            cout << "BAD VALUE";
            break;
    }
    cout << endl;
    return 0;
}

GCC 4.9,Clang 3.5.1和Intel C / C ++ Compiler 13.0.1似乎支持它(在http://gcc.godbolt.org/上试过)。另一方面,Visual C ++ 19没有(试过http://webcompiler.cloudapp.net/)。

答案 1 :(得分:25)

在C ++案例中,标签是常量表达式,而不是一般的表达式。你需要一系列if-then-else语句来做你想做的事。

或者,您可以枚举开关中的值。这种情况稍微快一点(尽管在像你这样的情况下并不重要),但它的可读性要差得多:

switch(score) {
    case 0: cout << "f"; break;
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
    case 10: cout << "e"; break;
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
    case 16:
    case 17:
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
    case 24:
    case 25: cout << "c"; break;
    // ...and so on, you get the idea...

}

答案 2 :(得分:16)

您可以使用一系列if / else if语句来解决此问题。在C ++中不能像这样使用Switch / case。

答案 3 :(得分:9)

可以使用std::mapswitch

来完成
enum Interval {
   One,
   Two,
   Three,
   NotFound };

// [0,10[ is One, [10,30[ is Two, [30,55[ is Three
std::map<int,Interval> imap { 
    { { 0, One }, 
      { 10, Two },
      { 30, Three },
      { 55, NotFound } };
Interval ivalue = NotFound;
auto f = imap.lower_bound( value );
if( f != imap.end() ) ivalue = f->second;
switch( ivalue ) {
    case One : ...
    case Two : ...
    case Three : ...
    default: ...
}

答案 4 :(得分:5)

在C ++中,switch语句只能匹配常量整数值:

switch (i)
{
    case 1:
    //... stuff
    break;
    case 2:
    //... stuff
    break;
    default:
    //... stuff
}

答案 5 :(得分:5)

有一个GCC extension可以完全满足您的需求。

答案 6 :(得分:4)

std::map::upper_bound + C ++ 11 lambdas

https://stackoverflow.com/a/35460297/895245提到lower_bound,但我们也可以摆脱enum那里的lambdas(如果你没有继承那就继承)。

#include <functional>
#include <iostream>
#include <map>

int main() {
    std::string ret;
    const std::map<int,std::function<void()>> m{
        {0, [&](){ ret = "too small"; }},
        {2, [&](){ ret = "[0,2)"; }},
        {5, [&](){ ret = "[2,5)"; }},
        {7, [&](){ ret = "[5,7)"; }},
    };
    const auto end = m.end();
    for (auto i = -1; i < 8; ++i) {
        auto it = m.upper_bound(i);
        if (it == end) {
            ret = "too large";
        } else {
            it->second();
        }
        std::cout << i << " " << ret << std::endl;
    }
}

输出:

-1 too small
0 [0,2)
1 [0,2)
2 [2,5)
3 [2,5)
4 [2,5)
5 [5,7)
6 [5,7)
7 too large

使用static

的方法中的用法

要在类中有效地使用此模式,请静态初始化lambda映射,否则每次都要从{0}开始构建它。

在这里,我们可以使用n log(n)方法变量的{}初始化:Static variables in class methods,但我们也可以使用以下所述的方法:static constructors in C++? I need to initialize private static objects

有必要将lambda context capture static转换为参数,或者未定义的参数:const static auto lambda used with capture by reference

产生与上面相同的输出的示例:

[&]

答案 7 :(得分:3)

该标准不允许这样做:

  

6.4.2 switch语句[stmt.switch]

     

[...] switch语句中的任何语句都可以用一个或多个case标签标记,如下所示:

     

case constant-expression :

     

其中,常量表达式应为整数常量表达式(5.19)。

换句话说,您只能使用扩展为单个整数“硬”编译时间常量的大小写值(例如case 5+6:enum {X = 3}; ... case X*X:)。

解决这个问题的方法是使用if - 语句。例如,替换

switch (x)
case 0..100:

你改为

if (x>=0 && x<=100)

答案 8 :(得分:2)

Switch-case对于测试范围不是一个很好的选择。最好的选择是使用多个if

if (score<0) cout << "BAD VALUE";
if (score == 0)  cout << "f";
if (score>0 && score<10) cout << "e";
if (score>=10 && score <25) cout << "d";
if (score>=25 && score <50) cout << "c";
if (score>=50 && score <100) cout << "b";

如果运行时间有问题,则以下解决方案会更快:

if (score == 0)  cout << "f";
else if (score<10) cout << "e";
else if (score <25) cout << "d";
else if (score <50) cout << "c";
else if (score <100) cout << "b";
else if (score>=100) cout << "a";
else cout << "BAD VALUE";

答案 9 :(得分:2)

我在基于分数的问题上遇到了同样的问题,而且“if / elseif”语句很好用,对于间隔我发现最好的选择(对我来说至少因为我喜欢它看起来如何,而且更容易我作为初学者看到我的错误)是“1 ... 10”。但是不要忘记在数字和点之间使用空格,否则程序会认为你的间隔是一个数字,你会得到一个错误“2多个小数点......”。希望它有所帮助。

int score;

int main()
{
    cout<<"Enter score"<<endl;
    cin>>score;

  switch(score){
    case 100:
        cout<<"Your score is Perfect"<<endl;
    break;
    case 90 ... 99:
        cout<<"You got A"<<endl;
    break;
    case 80 ... 89:
        cout<<"You got B"<<endl;
        break;
    case 70 ... 79:
        cout<<"You got C"<<endl;
        break;
    case 60 ... 69:
        cout<<"You got D"<<endl;
        break;
    case 50 ... 59:
        cout<<"You got E"<<endl;
        break;
    case 0 ... 49:
        cout<<"You got F"<<endl;}

  }

答案 10 :(得分:2)

这根本不是交换机的工作方式。它只需要单个值。你必须使用if-elseif块

答案 11 :(得分:1)

这对我有用。将标记除以10然后设置案例10和9以显示“A”(对于90-100之间的任何值,这将显示“A”。然后案例8显示“B”,则案例7将显示“ C“表示70-79之间的值等等。

#include <iostream>
using namespace std;

main ()
{
    int mark;
    cout << "enter your mark: ";
    cin >> mark;
    switch (mark/10)
    {
        case 10: case 9: cout << "A"; break;
        case 8: cout << "B"; break;
        case 7: cout << "C"; break;
        case 6: cout << "D"; break;
        case 5: cout << "PASS"; break;
        default: cout << "FAIL"; break;
    }
}

答案 12 :(得分:1)

您可以执行以下操作:

//summarize the range to one value
If score < 0
    score = -1

switch(score){
case 1:
    //...
    break;
case 2:
    //...
    break;
case -1:    //complete neg. range
    //...
    break;
//...

}

答案 13 :(得分:1)

切换案例语句可以替代将变量与几个变量进行比较的long if语句&#34; integral&#34;值(&#34;整数&#34;值只是可以表示为整数的值,例如char的值)。 switch语句的条件是一个值。案例说,如果它具有该案件之后的任何值,那么在冒号后面做任何事情。中断用于打破案例陈述。

因此,您无法使用此类条件语句。

The selective structure: switch

答案 14 :(得分:1)

我希望这是一种表达方式,易于理解的方式。

你可能会惊讶于gcc / clang等可以优化它生成的代码。我希望它至少和交换机/机箱一样高效。

#include <iostream>

template<class Value>
struct switcher
{
    constexpr switcher(Value const& value) : value_(value) {}
    constexpr switcher(Value const& value, bool enabled) : value_(value), enabled(enabled) {}

    template<class From, class To, class F>
    constexpr auto in_range(From&& from, To&& to, F&& f)
    {
        if (enabled and (from <= value_ and value_ <= to))
        {
            f();
            return switcher(value_, false);
        }
        else {
            return *this;
        }
    };

    template<class F>
    constexpr auto otherwise(F&& f)
    {
        if (enabled)
            f();
    }

    Value const& value_;
    const bool enabled = true;
};

template<class Value>
constexpr auto decision(Value const& value)
{
    return switcher<Value>(value);
}

void test(int x)
{
    decision(x)
            .in_range(0, 10, [&] { std::cout << x << " maps to option A\n"; })
            .in_range(11, 20, [&] { std::cout << x << " maps to option B\n"; })
            .otherwise([&] { std::cout << x << " is not covered\n"; });
}

int main(int argc, char **argv) {

    test(5);
    test(14);
    test(22);
}

答案 15 :(得分:0)

我知道这是一个古老的问题,但由于switch语句实际上是标签周围的包装,我发现goto可能(好)在这里使用。

    int value = 40;
    if (value < 10) {
        std::cout << "value < 10" << std::endl;
        goto end;
    }
    if (value < 50) {
        std::cout << "value < 50" << std::endl;
        goto end;
    }
    if (value > 30) {
        std::cout << "value > 30" << std::endl;
        goto end;
    }
end:
    // resume

这样,您可以省略所有else并保持紧凑。 使用goto时(通常),你应该小心。

答案 16 :(得分:0)

一个潜在有用的见解是switch接受一个表达式,因此您可以将多个输入值折叠为一个切换案例。这很难看,但需要考虑:

switch (score / 10)
{
  case 10:
    cout << "a";
    break;

  case 9: case 8: case 7: case 6: case 5:
    cout << "b";
    break;

  case 4: case 3:
    cout << "c";
    break;

  case 2:
    if (score >= 25)
    {
        cout << "c";
        break;
    }
    // else fall through...
  case 1:
    cout << "d";
    break;

  case 0:
    cout << (score > 0 ? "e" : "f");
    break;

  default:
    cout << "BAD VALUE";
    break;
}

当然,您可以除以5并且case 4:(20-24)与case 5:(25-29)相比if case 2:/10 ,但{{1}}可以说更直观。

答案 17 :(得分:0)

这样的东西?

case 'A'..'Z' where a not in ['I','L','O']:

不幸的是,我所知道的编译器没有实现特定的扩展,尽管GCC可以像其他答案所指出的那样执行范围。为了便于携带,您可以剪切并粘贴此DWTFYW许可的代码段。如果您使用的是自定义枚举,则可以使用代码生成来制作类似的内容。

#define CASE_NUMBER \
 case'0':case'1':case'2':case'3':case'4':\
 case'5':case'6':case'7':case'8':case'9'
#define CASE_ALPHA_LOWER \
 case'a':case'b':case'c':case'd':\
 case'e':case'f':case'g':case'h':\
 case'i':case'j':case'k':case'l':\
 case'm':case'n':case'o':case'p':\
 case'q':case'r':case's':case't':\
 case'u':case'v':case'w':case'x':\
 case'y':case'z'
#define CASE_ALPHA_UPPER \
 case'A':case'B':case'C':case'D':\
 case'E':case'F':case'G':case'H':\
 case'I':case'J':case'K':case'L':\
 case'M':case'N':case'O':case'P':\
 case'Q':case'R':case'S':case'T':\
 case'U':case'V':case'W':case'X':\
 case'Y':case'Z'
#define CASE_ALPHA CASE_ALPHA_UPPER:CASE_ALPHA_LOWER
#define CASE_ALPHANUM CASE_ALPHA:CASE_NUMBER

如果您访问GHCI(例如https://ghc.io/的在线版本),您可能只需生成所需内容并将其粘贴到标题中,例如

foldl (++) "" ["case" ++ show x ++ ":" | x <- ['A'..'Z'], not $ x `elem` ['I','L','O']]