lets say i have a bunch of bins, each of which holds a range of numbers. an example is:
bin 1: 0-8
bin 2: 9-16
bin 3: 17-24
etc
is there a way to use a switch statement to figure out which bin a number belongs to? i'm trying to figure out how to make cases reflect that 开发者_如何学Ca number is within a range, but they don't seem to be 'constant expressions' so i'm not sure it's possible..
edit
I should probably be more accurate; my bins are powers of two...
bin 1: 0 to 2^3
bin 2: 2^3 + 1 to 2^4
bin 3: 2^4 + 1 to 2^5
etc
You can't use ranges for case
labels in C - only single (constant-expression) values.
If the ranges are small, like your example, then you can do this:
switch (value)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
bin = 1;
break;
case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16:
bin = 2;
break;
case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24:
bin = 3;
break;
default:
}
Alternatively, you can use a lookup table:
static const int val_bin[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0 to 8 */
2, 2, 2, 2, 2, 2, 2, 2, /* 9 to 16 */
3, 3, 3, 3, 3, 3, 3, 3 /* 17 to 24 */
};
bin = val_bin[value];
Or, in some cases, you can determine a simple formula. Your current example appears to be such a case:
bin = 1 + (value - 1 / 8);
Response to edit:
For your updated question, on powers of 2, this is actually quite easy. You can use the "bit-smearing" technique to munge all values that lie between two powers-of-two into one value (this assumes you are using unsigned long
for value
, with a maximum value of 2^32 - 1
):
if (value > 0)
value -= 1; /* This is needed because your specified bins are "off by one" from the natural definitions */
value |= value >> 16;
value |= value >> 8;
value |= value >> 4;
value |= value >> 2;
value |= value >> 1;
switch (value)
{
case 0x00000000UL: /* 0, 1 */
case 0x00000001UL: /* 2 */
case 0x00000003UL: /* 2^1 + 1 ... 2^2 */
case 0x00000007UL: /* 2^2 + 1 ... 2^3 */
bin = 1;
break;
case 0x0000000fUL: /* 2^3 + 1 ... 2^4 */
bin = 2;
break;
case 0x0000001fUL: /* 2^4 + 1 ... 2^5 */
bin = 3;
break;
/* etc */
}
You can cascade them though:
case 0:case 1: case 2: case 3: case 4: ..... case 8: do_something(); break; case 9: case 10: ....... etc
If your compiler is GCC, you are lucky. GCC has an extension called case ranges, that allows you to write your switch like this:
switch (value) {
case 0 ... 8:
bin = 1;
break;
case 9 ... 16:
bin = 2;
break;
/* and so on */
}
It is not standard C!
精彩评论