簡體   English   中英

如何在 C 中的 switch case 語句中使用范圍?

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

我的邏輯是:

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':

作為語言擴展GCC編譯器支持以下情況范圍

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

Clang / LLVM也接受此語言擴展。 因此,如果您能夠將代碼限制在GCC和Clang編譯器中,請使用它。

另請參見

我不知道為什么這個擴展沒有包含在C11標准中。

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
      ...
      }
   }

選項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

C不支持除單個整數之外的大小寫值(或類似整數的東西 - 字符,枚舉值)。 所以你的選擇是:

  • 正如pzaenger在一條現已刪除的評論中所建議的那樣:將您正在使用的數字轉換為可以打開的數字(在這種情況下,除以10)。
  • 多個案例陳述(利用漏洞): case 1: case 2: case 3: ... case 10: do_something();
  • 使用if而不是case

您將無法使用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);
        }
    }
}

在C編程語言中, switch()語句中使用的case語句必須指定編譯器可以某種方式轉換為常量的值。 case語句中使用的每個值在switch()的范圍內必須是唯一的。 如果case語句都不匹配switch()語句中的表達式,則default關鍵字表示缺省值。

另外,請查看Duff的設備,以顯示switch()case的有趣用法。 看看Duff的設備是如何工作的?

因此,下面顯示了switch()中正確的case語句的幾個示例:

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

如果您仍想使用帶有遠程case語句的switch() ,則可以執行的操作是提供一些將表達式折疊為一個或多個特定常量值的機制。

因此,在一個簡單,瑣碎的例子中,您可以執行以下操作。 這是一個簡單的案例來展示最終使簡單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;
}

c中的switch語句只能對常量表達式進行操作,case語句不能包含動態比較。

C中的“常量表達式”是什么,不是什么?

對於這個簡單的if / else結構可以更清楚和更簡單的東西,取決於編譯器,您的case語句可能會被轉換為一系列分支比較語句。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM