Ma logique est:
if number is between 1 to 10, execute first case statement
if number is from 20 to 30, execute second case statement
existe-t-il une solution autre que celle ci-dessous?
case '1' ... '10':
case '20' ... '30':
Le compilateur GCC prend en charge, en tant que extension de langue, les plages de casse like:
switch(i) {
case 0 ... 9: return true;
default: return false;
}
Cette extension de langue est également acceptée par Clang/LLVM . Alors utilisez-le si vous pouvez vous permettre de restreindre votre code aux compilateurs GCC & Clang.
Voir aussi this .
Je n'ai aucune idée pourquoi cette extension n'a pas été incluse dans C11 standard.
void SwitchDemo(int value)
{
switch(value / 10)
{
case 0: ...; break; // 0 - 9
case 1: ...; break; // 10 - 19
...
}
}
ou, spécifique aux domaines de questions:
void SwitchDemo(int value)
{
switch((value-1) / 10)
{
case 0: ...; break; // 1 - 10
case 1: ...; break; // 11 - 20
...
}
}
Option 1: utilisez case 0
pour 0-9
, case 1
pour 11-20
et ainsi de suite.
Option 2: utilisez if
Option 3:
Une autre façon minable consiste à utiliser des cas comme celui-ci:
#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;
}
Sortie:
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 ne prend pas en charge les valeurs de casse autres que les entiers simples (ou les éléments semblables à des entiers - caractères, valeurs d’énumération). Donc, vos options sont:
case 1: case 2: case 3: ... case 10: do_something();
if
plutôt que case
.Vous ne pourrez pas faire cela en C standard avec une instruction switch-case
.
(comme d’autres réponses l’ont souligné, certains compilateurs ont des extensions non standard pour cela)
Au lieu de cela, je recommande de créer une structure de données telle que:
struct RangeData
{
int start;
int end;
void (*func)(int);
};
RangeData ranges[] = { { 1, 10, Handle10s },
{ 20, 30, Handle20s },
{5000, 10000, HandleBigNumbers} };
Ensuite, il devrait être très facile de créer une petite boucle qui parcourt, trouve la plage appropriée et appelle la fonction appropriée.
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);
}
}
}
Dans le langage de programmation C, l'instruction case
utilisée dans une instruction switch()
doit spécifier une valeur que le compilateur peut transformer en une constante. Chacune des valeurs utilisées dans les instructions case
doit être unique dans le cadre de la fonction switch()
. Le mot clé default
indique la valeur par défaut si aucune des instructions case
ne correspond à l'expression de l'instruction switch()
.
En passant, jetez un œil à Duff's Device pour montrer une utilisation intéressante de switch()
et case
. Voir Comment fonctionne l'appareil de Duff?
Donc, voici quelques exemples d'instructions case
correctes dans un 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;
}
Si vous souhaitez toujours utiliser une switch()
avec des instructions à distance case
, vous pouvez fournir un mécanisme permettant de plier l'expression en une ou plusieurs valeurs constantes spécifiques.
Ainsi, dans un exemple simple et trivial, vous pourriez faire quelque chose comme ce qui suit. C’est un cas trivial pour montrer la technique qui finit par rendre opaque la logique des simples déclarations if
. Cette technique peut être utile pour les décisions complexes et la classification qui peut être pliée en un simple ensemble de constantes.
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;
}
L'approche de pliage peut être utile lorsque vous obtenez plusieurs résultats différents, en utilisant éventuellement un filtre pour essayer de classer un élément de données.
#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;
}