C语言 如何在 C 中的 switch case 语句中使用范围?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36748934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 10:24:06  来源:igfitidea点击:

How can I use ranges in a switch case statement in C?

cswitch-statement

提问by user3205621

My logic is:

我的逻辑是:

if number is between 1 to 10, execute first case statement
if number is from 20 to 30, execute second case statement

is there a solution other than the one below?

除了以下解决方案之外还有其他解决方案吗?

case '1' ... '10':
case '20' ... '30':

回答by Basile Starynkevitch

The GCCcompiler supports, as a language extension, case rangeslike:

GCC编译器支持,作为语言的扩展案件范围,如:

 switch(i) {
    case 0 ... 9: return true;
    default: return false;
 }

This language extension is also accepted by Clang/LLVM. So use it if you can afford restricting your code to GCC & Clang compilers.

Clang/LLVM也接受此语言扩展。因此,如果您能负担得起将代码限制为 GCC 和 Clang 编译器,请使用它。

See also this.

另请参见

I have no idea why this extension was not included in C11standard.

我不知道为什么这个扩展没有包含在C11标准中。

回答by Mahonri Moriancumer

void SwitchDemo(int value)
   {
   switch(value / 10)
      {
      case 0: ...; break; // 0 - 9
      case 1: ...; break; // 10 - 19
      ...
      }
   }

or, specific to the question ranges:

或者,特定于问题范围:

void SwitchDemo(int value)
   {
   switch((value-1) / 10)
      {
      case 0: ...; break; // 1 - 10
      case 1: ...; break; // 11 - 20
      ...
      }
   }

回答by riteshtch

Option 1: use case 0for 0-9, case 1for 11-20and so on.

选项 1:使用case 0for 0-9case 1for11-20等等。

Option 2: use if

选项 2:使用 if

Option 3:

选项 3:

Another shabby way is using fall through cases like this:

另一种糟糕的方式是使用这样的fall through case:

#include <stdio.h>

int main(void) {
    int i=1;

    for(i=1;i<=25;i++)
    {
    switch(i)
    {
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
        case 9:
        case 10:
            printf("%d  is in between 1-10\n", i);
            break;

        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
        case 16:
        case 17:
        case 18:
        case 19:
        case 20:
            printf("%d  is in between 11-20\n", i);
            break;

        default:
            printf("%d  is above 20\n", i);
    }
    }
    return 0;
}

Output:

输出:

1  is in between 1-10
2  is in between 1-10
3  is in between 1-10
4  is in between 1-10
5  is in between 1-10
6  is in between 1-10
7  is in between 1-10
8  is in between 1-10
9  is in between 1-10
10  is in between 1-10
11  is in between 11-20
12  is in between 11-20
13  is in between 11-20
14  is in between 11-20
15  is in between 11-20
16  is in between 11-20
17  is in between 11-20
18  is in between 11-20
19  is in between 11-20
20  is in between 11-20
21  is above 20
22  is above 20
23  is above 20
24  is above 20
25  is above 20

https://ideone.com/Cw6HDO

https://ideone.com/Cw6HDO

回答by Gareth McCaughan

C doesn't support case values other than single integers (or integer-like things -- characters, enumeration values). So your options are:

除了单个整数(或类似整数的东西——字符、枚举值),C 不支持大小写值。所以你的选择是:

  • As suggested by pzaenger in a now-deleted comment: transform the number you're working with into something you canswitch on (in this case, divide by 10).
  • Multiple case statements (taking advantage of fallthrough): case 1: case 2: case 3: ... case 10: do_something();
  • Use ifrather than case.
  • 正如 pzaenger 在现已删除的评论中所建议的那样:将您正在使用的数字转换为您可以打开的数字(在这种情况下,除以 10)。
  • 多个 case 语句(利用 fallthrough): case 1: case 2: case 3: ... case 10: do_something();
  • 使用if而不是case.

回答by Richard Chambers

In the C programming language the casestatement used in a switch()statement must specify a value that the compiler can turn into a constant in some way. Each of the values used in the casestatements must be unique within the scope of the switch(). The defaultkeyword indicates the default if none of the casestatements match the expression in the switch()statement.

在 C 编程语言中,case语句中使用的switch()语句必须指定一个值,编译器可以通过某种方式将其转换为常量。case语句中使用的每个值在switch(). 该default关键字表示默认如果没有任何的case声明相匹配的表达switch()语句。

As an aside, check out Duff's Device to show an interesting use of switch()and case. See How does Duff's device work?

顺便说一句,请达夫设备演示一个有趣的使用switch()case。请参阅Duff 的设备如何工作?

So the following shows several examples of proper casestatements in a switch():

因此,以下显示了casea中正确语句的几个示例switch()

#define XXVAL 2
#define CASETEST(x) (x + 5)

int iValue;
//  set the value of the variable iValue at some point
switch (iValue) {
case 0:
    // do the case if iValue == 0
    break;
case XXVAL:
    // do the case if iValue == XXVAL
    break;
case CASETEST(3):
    // do the case if iValue == CASETEST(3)
    // works because preprocessor generates the source text which is
    // then compiled and the expression can be resolved to a constant
    break;
case CASETEST(5) * 2:
    // do the case if iValue == CASETEST(5) * 2
    // works because preprocessor generates the source text which is
    // then compiled and the expression can be resolved to a constant
    break;
default:
    break;
}

What you can do if you still want to use a switch()with ranged casestatements is to provide some mechanism to fold the expression into one or more specific constant values.

如果您仍然想使用switch()带范围的case语句,您可以做的是提供某种机制来将表达式折叠成一个或多个特定的常量值。

So in a simple, trivial example you could do something like the following. This is a trivial case to show the technique which ends up making the logic of the simple ifstatements opaque. This technique can be useful for complex decisions and classification that can be folded into a simple set of constants.

因此,在一个简单、琐碎的示例中,您可以执行以下操作。这是一个简单的案例,展示了最终使简单if语句的逻辑变得不透明的技术。这种技术对于复杂的决策和分类很有用,这些决策和分类可以折叠成一组简单的常量。

int foldit (int iValue)
{
    if (iValue < 5000) return 0;
    else if (iValue < 10000) return 1;
    else if (ivalue < 20000) return 2;
    else return 9999;   // triggers the default part of the switch
}

switch (foldit(iValue)) {
case 0:
    // do what is needed for up to but not including 5000
    break;
case 1:
    // do what is needed for 5000 up to but not including 10000
    break;
case 2:
    // do what is needed for 10000 up to but not including 20000
    break;
default:
    // handle anything else
    break;
}

Where the fold approach can be helpful is when you have several different results perhaps using a filter to try to classify a data item.

当您有几个不同的结果可能使用过滤器尝试对数据项进行分类时,折叠方法可能会有所帮助。

#define type1  0x00001
#define type2  0x00002
#define type3  0x00004
#define type4  0x00008

struct datatype {
    int iVal;
    int jVal; 
};

unsigned long is_a_type1(struct datatype * thing)
{
    unsigned long retVal = 0;   // initialize to not a type1, set to type1 if turns out to be
    // do checks for the type and if so set retVal to type1 if it matches
    return retVal;
}

unsigned long is_a_type2(struct datatype * thing)
{
    unsigned long retVal = 0;   // initialize to not a type2, set to type2 if turns out to be
    // do checks for the type and if so set retVal to type2 if it matches
    return retVal;
}

unsigned long is_a_type3(struct datatype * thing)
{
    unsigned long retVal = 0;   // initialize to not a type3, set to type3 if turns out to be
    // do checks for the type and if so set retVal to type3 if it matches
    return retVal;
}

unsigned long is_a_type4(struct datatype * thing)
{
    unsigned long retVal = 0;   // initialize to not a type4, set to type4 if turns out to be
    // do checks for the type and if so set retVal to type4 if it matches
    return retVal;
}

unsigned long classify (struct datatype *thing)
{
    unsigned long ulTestResult = 0;

    // test to see if this is a type1 thing
    ulTestResult |= is_a_type1(thing);

    // test to see if this is a type2 thing
    ulTestResult |= is_a_type2(thing);

    // test to see if this is a type3 thing
    ulTestResult |= is_a_type3(thing);

    // test to see if this is a type4 thing
    ulTestResult |= is_a_type4(thing);

    return ulTestResult;
}

int main ()
{
    struct datatype myThing;
    //  other source code then
    switch (classify(&myThing)) {
    case type1 | type2 | type3:
        // do stuff if this is a type1, type2, and type3 but not type4
        // that is classify() determined that myThing matched all three types.
        break;
    case type1:
        // do stuff if type1 which includes stuff you do for type2 as well under
        // special values of myThing.
        if (myThing.iVal < 50) {
            case type2:
                // at this point we have type2 case stuff that we do. Code above is skipped
                // and the switch () will jump straight to here if classify() is type2.
                //
                // Also stuff we do if type1 and myThing.iVal < 50
                // in other words this code is execute if classify(&myThing) is type2 or
                // if classify(&myThink) is type1 and there is a special processing for myThing.iVal < 50
                break;  // if classify() type2 or if classify() type1 and myThing.ival < 50
            }
        // do stuff if only type1 and myThing.iVal >= 50
        break;
    case type2 | type3:
        // do stuff if type2 and type3 matched but none of the others.
        break;
    default:
        // any other case
        break;
    }
    return 0;
}

回答by maxlazar

Switch statements in c can only operate on a constant expression, the case statements cannot include dynamic comparisons.

c 中的 switch 语句只能对常量表达式进行操作,case 语句不能包含动态比较。

Example of something which is, and is not, a "Constant Expression" in C?

在 C 中是和不是“常量表达式”的示例?

For something this simple an if/else structure could be clearer and simpler, depending on the compiler your case statement may be translated into a series of branching comparison statements anyways.

对于这么简单的事情,if/else 结构可能会更清晰、更简单,这取决于编译器,您的 case 语句可能会被翻译成一系列分支比较语句。