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

时间:2016-04-20 15:45:37

标签: c switch-statement

我的逻辑是:

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

除了下面的解决方案之外还有解决方案吗?

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

7 个答案:

答案 0 :(得分:17)

GCC编译器支持语言扩展case ranges,如:

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

Clang/LLVM也接受此语言扩展程序。因此,如果您能够将代码限制为GCC& Clang编译器。

另见this

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

答案 1 :(得分:5)

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

或者,具体到问题范围:

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

答案 2 :(得分:4)

选项1:对case 0使用0-9case 1使用11-20,依此类推。

选项2:使用if

选项3:

另一个破旧的方法是使用这样的案例:

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

输出:

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

答案 3 :(得分:1)

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

  • 正如pzaenger在现在删除的评论中所建议的那样:将您正在使用的数字转换为可以开启的内容(在这种情况下,除以10)。
  • 多个案例陈述(利用漏洞):case 1: case 2: case 3: ... case 10: do_something();
  • 使用if而不是case

答案 4 :(得分:0)

您将无法使用switch-case声明在标准C中执行此操作 (正如其他答案所指出的,某些编译器具有非标准扩展来启用此功能)

相反,我建议制作一个数据结构,例如:

struct RangeData
{
    int start;
    int end;
    void (*func)(int);
};

RangeData ranges[] = { {   1,    10, Handle10s       }, 
                       {  20,    30, Handle20s       },
                       {5000, 10000, HandleBigNumbers} };

然后,应该很容易制作一个循环的微小循环,找到合适的范围,并调用正确的函数。

void DoNumber(int value)
{
    for(int i=0; i<ARRAYSIZE(ranges); ++i)
    {
        if (ranges[i].start <= value && value <= ranges[i].end)
        {
            ranges[i].func(value);
        }
    }
}

答案 5 :(得分:0)

在C编程语言中,case语句中使用的switch()语句必须指定编译器可以某种方式转换为常量的值。 case语句中使用的每个值在switch()范围内必须是唯一的。如果default语句中没有一个与case语句中的表达式匹配,则switch()关键字表示默认值。

另外,请查看Duff的设备,以显示switch()case的有趣用法。见How does Duff's device work?

因此,下面显示了case中正确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;
}

如果您仍想使用范围为switch()语句的case,则可以执行的操作是提供一些机制将表达式折叠为一个或多个特定常量值。

因此,在一个简单而琐碎的例子中,您可以执行以下操作。这是一个简单的案例来展示最终使简单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;
}

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

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

答案 6 :(得分:-1)

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

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

对于这个简单的if / else结构可能更清晰,更简单,取决于编译器,您的case语句可能会被转换为一系列分支比较语句。