私の論理は:
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 [〜#〜] コンパイラは、言語拡張として、 case範囲 のような:
switch(i) {
case 0 ... 9: return true;
default: return false;
}
この言語拡張は Clang/LLVM でも受け入れられます。したがって、コードをGCCおよびClangコンパイラーに制限する余裕がある場合に使用してください。
this もご覧ください。
この拡張機能が 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-9
、case 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
Cは、単一の整数(または整数のようなもの-文字、列挙値)以外のケース値をサポートしていません。オプションは次のとおりです。
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()
のスコープ内で一意でなければなりません。 default
キーワードは、case
ステートメントがswitch()
ステートメントの式に一致しない場合のデフォルトを示します。
余談ですが、switch()
とcase
の興味深い使用法を示すために、Duffのデバイスをチェックしてください。 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()
を使用したい場合にできることは、式を1つ以上の特定の定数値にフォールドするメカニズムを提供することです。
そのため、単純で些細な例では、次のようなことができます。これは、単純な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;
}
_