By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,918 Members | 1,852 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,918 IT Pros & Developers. It's quick & easy.

switch { } - case for range

P: n/a

I was checking out the C-FAQ and read here (
http://c-faq.com/misc/nonconstcase.html ) that:
" case labels are limited to single, constant, integral expression ".

However, I have been using case with ranges for a long while ( gcc,
VC++) so either the FAQ calls for an update or those two compilers
provide this functionality as an extension.

example;
switch (a)
{
case 1 ... 10:
// code
break;

case 11 ... 50:
// code
break;

case 800:
// code
break;

default:
// code
break;
}

Sep 6 '06 #1
Share this Question
Share on Google+
21 Replies


P: n/a
"markpapadakis" <ma***********@gmail.comwrites:
I was checking out the C-FAQ and read here (
http://c-faq.com/misc/nonconstcase.html ) that:
" case labels are limited to single, constant, integral expression ".

However, I have been using case with ranges for a long while ( gcc,
VC++) so either the FAQ calls for an update or those two compilers
provide this functionality as an extension.
It's an extension.
--
Go not to Usenet for counsel, for they will say both no and yes.
Sep 6 '06 #2

P: n/a
BRG
markpapadakis wrote:
I was checking out the C-FAQ and read here (
http://c-faq.com/misc/nonconstcase.html ) that:
" case labels are limited to single, constant, integral expression ".

However, I have been using case with ranges for a long while ( gcc,
VC++) so either the FAQ calls for an update or those two compilers
provide this functionality as an extension.

example;
switch (a)
{
case 1 ... 10:
// code
break;

case 11 ... 50:
// code
break;

case 800:
// code
break;

default:
// code
break;
}
This doesn't work with VC++ version 8 and I don't recall it working on
earlier versions either.

Brian Gladman

Sep 6 '06 #3

P: n/a
markpapadakis wrote:
I was checking out the C-FAQ and read here (
http://c-faq.com/misc/nonconstcase.html ) that:
" case labels are limited to single, constant, integral expression ".

However, I have been using case with ranges for a long while ( gcc,
VC++) so either the FAQ calls for an update or those two compilers
provide this functionality as an extension.
[snip example]

C doesn't have ranges. What you describe is an extension, one which is
clearly documented as such in the gcc documentation. What version of
VC++ are you using that allows this?

Robert Gamble

Sep 6 '06 #4

P: n/a

Robert Gamble wrote:
markpapadakis wrote:
I was checking out the C-FAQ and read here (
http://c-faq.com/misc/nonconstcase.html ) that:
" case labels are limited to single, constant, integral expression ".

However, I have been using case with ranges for a long while ( gcc,
VC++) so either the FAQ calls for an update or those two compilers
provide this functionality as an extension.

[snip example]

C doesn't have ranges. What you describe is an extension, one which is
clearly documented as such in the gcc documentation. What version of
VC++ are you using that allows this?

Robert Gamble
I was wrong. It does not work with VC++. It has been a long while since
I used it and I thought it was supported there as well.

Thank you for the answer to the question.

Sep 6 '06 #5

P: n/a
markpapadakis wrote:
I was checking out the C-FAQ and read here (
http://c-faq.com/misc/nonconstcase.html ) that:
" case labels are limited to single, constant, integral expression ".

However, I have been using case with ranges for a long while ( gcc,
VC++) so either the FAQ calls for an update or those two compilers
provide this functionality as an extension.
It's an extension.

--
Clark S. Cox III
cl*******@gmail.com
Sep 6 '06 #6

P: n/a
markpapadakis wrote:
I was checking out the C-FAQ and read here (
http://c-faq.com/misc/nonconstcase.html ) that:
" case labels are limited to single, constant, integral expression ".

However, I have been using case with ranges for a long while ( gcc,
VC++) so either the FAQ calls for an update or those two compilers
provide this functionality as an extension.

example;
switch (a)
{
case 1 ... 10:
// code
break;

case 11 ... 50:
// code
break;

case 800:
// code
break;

default:
// code
break;
}
What is your experience with this extension?

Is it really useful?

How many times did you use it?

I would be interested in knowing if it makjes sense to
implement it in lcc-win32.

jacob
Sep 6 '06 #7

P: n/a
On Wed, 06 Sep 2006 22:09:45 +0200, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.frwrote:
>markpapadakis wrote:
>switch (a)
{

What is your experience with this extension?
For what its worth, my experience is that its really useful if you're
a Visual Basic programmer trying to write C in the style of VB.

For myself I consider this A Very Bad Idea (tm), never ever try to use
one language in the idiom of another. Consider the early editions of
Num Rec in C as a classic case-study. I mean, why buy a scooter to
haul logs?
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Sep 6 '06 #8

P: n/a

jacob navia wrote:
markpapadakis wrote:
I was checking out the C-FAQ and read here (
http://c-faq.com/misc/nonconstcase.html ) that:
" case labels are limited to single, constant, integral expression ".

However, I have been using case with ranges for a long while ( gcc,
VC++) so either the FAQ calls for an update or those two compilers
provide this functionality as an extension.

example;
switch (a)
{
case 1 ... 10:
// code
break;

case 11 ... 50:
// code
break;

case 800:
// code
break;

default:
// code
break;
}

What is your experience with this extension?

Is it really useful?

How many times did you use it?

I would be interested in knowing if it makjes sense to
implement it in lcc-win32.

jacob

I am using it quite often. Its useful it eliminates the need for
conditional statements ( wherever conditional statements can be used,
of course ) , provides for easier to manage/understand code and perhaps
reaps any performance benefits versus conditional statements.

Mark

Sep 6 '06 #9

P: n/a
markpapadakis wrote:
jacob navia wrote:
>markpapadakis wrote:
>>I was checking out the C-FAQ and read here (
http://c-faq.com/misc/nonconstcase.html ) that:
" case labels are limited to single, constant, integral
expression ".

However, I have been using case with ranges for a long while
( gcc, VC++) so either the FAQ calls for an update or those
two compilers provide this functionality as an extension.

example;
switch (a)
{
case 1 ... 10:
// code
break;

case 11 ... 50:
// code
break;

case 800:
// code
break;

default:
// code
break;
}

What is your experience with this extension?

Is it really useful?

How many times did you use it?

I would be interested in knowing if it makjes sense to
implement it in lcc-win32.

I am using it quite often. Its useful it eliminates the need for
conditional statements ( wherever conditional statements can be
used, of course ) , provides for easier to manage/understand code
and perhaps reaps any performance benefits versus conditional
statements.
Why in heavens name use it and become non-portable, when the
portable code (following) is clearer:

if ((a >= 1) && (a <= 10)) firstcode();
else if ((a 10) && (a <= 50)) secondcode();
else if (a == 800) thirdcode();
else defaultcode();

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Sep 7 '06 #10

P: n/a
In article <44***************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:
>Why in heavens name use it and become non-portable, when the
portable code (following) is clearer:

if ((a >= 1) && (a <= 10)) firstcode();
else if ((a 10) && (a <= 50)) secondcode();
else if (a == 800) thirdcode();
else defaultcode();
That's fine in that case, but I have often had cases where there are a
few large ranges and lots of single cases (e.g. when considering a
character during the parsing of some expression). Of course you can
split it into some tests followed by a switch, but ranges would be
neater and allow the compiler to choose the most efficient set of
comparisons.

-- Richard
Sep 7 '06 #11

P: n/a


Richard Tobin wrote On 09/07/06 08:01,:
In article <44***************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:

>>Why in heavens name use it and become non-portable, when the
portable code (following) is clearer:

if ((a >= 1) && (a <= 10)) firstcode();
else if ((a 10) && (a <= 50)) secondcode();
else if (a == 800) thirdcode();
else defaultcode();


That's fine in that case, but I have often had cases where there are a
few large ranges and lots of single cases (e.g. when considering a
character during the parsing of some expression). Of course you can
split it into some tests followed by a switch, but ranges would be
neater and allow the compiler to choose the most efficient set of
comparisons.
Are you looking for

case 'a' ... 'z':
case 'A' ... 'Z':
process_alphabetic(ch);
break;

? If so, CBF's solution (now using isalpha() in a test)
is superior on several grounds, correctness among them.

--
Er*********@sun.com

Sep 7 '06 #12

P: n/a
In article <1157646365.318129@news1nwk>,
Eric Sosman <Er*********@sun.comwrote:
Are you looking for

case 'a' ... 'z':
case 'A' ... 'Z':
process_alphabetic(ch);
break;
Something not unlike that, but I generally have Unicode values.
>? If so, CBF's solution (now using isalpha() in a test)
is superior on several grounds, correctness among them.
Presumably you are referring to the possibility of a system where the
alphabetic characters are not consecutive, but on such a system
isalpha() would not give the right results for my Unicode characters -
I would have to use numeric ranges.

-- Richard

Sep 7 '06 #13

P: n/a
On 7 Sep 2006 12:01:14 GMT, in comp.lang.c , ri*****@cogsci.ed.ac.uk
(Richard Tobin) wrote:
>In article <44***************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:
>>Why in heavens name use it and become non-portable, when the
portable code (following) is clearer:

if ((a >= 1) && (a <= 10)) firstcode();
else if ((a 10) && (a <= 50)) secondcode();
else if (a == 800) thirdcode();
else defaultcode();

That's fine in that case, but I have often had cases where there are a
few large ranges and lots of single cases (e.g. when considering a
character during the parsing of some expression). Of course you can
split it into some tests followed by a switch, but ranges would be
neater and allow the compiler to choose the most efficient set of
comparisons.
I would submit that the algo was probably flawed, if you found
yourself in this situation.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Sep 7 '06 #14

P: n/a
In article <8q********************************@4ax.com>,
Mark McIntyre <ma**********@spamcop.netwrote:
>>That's fine in that case, but I have often had cases where there are a
few large ranges and lots of single cases (e.g. when considering a
character during the parsing of some expression). Of course you can
split it into some tests followed by a switch, but ranges would be
neater and allow the compiler to choose the most efficient set of
comparisons.
>I would submit that the algo was probably flawed, if you found
yourself in this situation.
Why is that?

Here's an example. I want to classify Unicode characters according
to whether they are XML 1.1 name characters, name start characters, or
other. What is wrong with writing something like:

/* See http://www.w3.org/TR/xml11/#NT-NameStartChar */
switch(c)
{
case 0x3a: /* colon */
case 0x41...0x5a: /* A-Z */
case 0x5f: /* underscore */
case 0x61...0x7a: /* a-z */
case 0xC0...0xD6:
case 0xD8...0xF6:
case 0xF8...0x2FF:
case 0x370...0x37D:
case 0x37F...0x1FFF:
case 0x200C...0x200D:
case 0x2070...0x218F:
case 0x2C00...0x2FEF:
case 0x3001...0xD7FF:
case 0xF900...0xFDCF:
case 0xFDF0...0xFFFD:
case 0x10000...0xEFFF:
return NameStart;
case 0x2d: /* hyphen */
case 0x2e: /* full stop */
case 0x30...0x39: /* 0-9 */
case 0xb7:
case 0x300...0x36f:
case 0x203f...0x2040:
return NameChar;
default:
return Other;
}

Obviously there are other ways to do it, but I don't see why this way
(which directly reflects the standard it is implementing) is "flawed".

-- Richard
Sep 7 '06 #15

P: n/a
boa
* Richard Tobin wrote, On 07.09.2006 23:08:
[snip]
case 0x10000...0xEFFF:
Shouldn't that be 0xEFFFF?

Boa
Sep 8 '06 #16

P: n/a
CBFalconer wrote:
Why in heavens name use it and become non-portable, when the
portable code (following) is clearer:

if ((a >= 1) && (a <= 10)) firstcode();
else if ((a 10) && (a <= 50)) secondcode();
else if (a == 800) thirdcode();
else defaultcode();
Too bad C didn't keep the range syntax from BCPL. Then you could have
used the even clearer:

if (1 <= a <= 10) firstcode();
else if (10 < a <= 50) secondcode();
else if (a == 800) thirdcode();
else defaultcode();

--
Sven Axelsson

Sep 8 '06 #17

P: n/a
sv***********@gmail.com wrote:
>
CBFalconer wrote:
>Why in heavens name use it and become non-portable, when the
portable code (following) is clearer:

if ((a >= 1) && (a <= 10)) firstcode();
else if ((a 10) && (a <= 50)) secondcode();
else if (a == 800) thirdcode();
else defaultcode();

Too bad C didn't keep the range syntax from BCPL. Then you could
have used the even clearer:

if (1 <= a <= 10) firstcode();
else if (10 < a <= 50) secondcode();
else if (a == 800) thirdcode();
else defaultcode();
I disagree. The grammar needed to parse such constructs is a
horror, and the result is all sorts of silly errors. SPL (Algol
based HP System Programming Language for the HP3000) had that
construct, and it created nothing but trouble.

--
Some informative links:
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
Sep 8 '06 #18

P: n/a
On 7 Sep 2006 22:08:47 GMT, in comp.lang.c , ri*****@cogsci.ed.ac.uk
(Richard Tobin) wrote:
>In article <8q********************************@4ax.com>,
Mark McIntyre <ma**********@spamcop.netwrote:
>>I would submit that the algo was probably flawed, if you found
yourself in this situation.

Here's an example. I want to classify Unicode characters according
to whether they are XML 1.1 name characters, name start characters, or
other. What is wrong with writing something like:
for starters, case{} is clearly the wrong method for this sort of
process. It'd be a lot easier and clearer with an if statement.
>Obviously there are other ways to do it, but I don't see why this way
(which directly reflects the standard it is implementing) is "flawed".
*ahem*
Directly implementing a standard is very likely NOT to be the most
efficient or sensible way to write code. Standards are written to be
understood by humans.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Sep 8 '06 #19

P: n/a
In article <9t********************************@4ax.com>,
Mark McIntyre <ma**********@spamcop.netwrote:
>Directly implementing a standard is very likely NOT to be the most
efficient or sensible way to write code. Standards are written to be
understood by humans.
So are programs, I hope.

-- Richard
Sep 8 '06 #20

P: n/a
CBFalconer wrote:
sv***********@gmail.com wrote:
>CBFalconer wrote:
>>Why in heavens name use it and become non-portable, when the
portable code (following) is clearer:

if ((a >= 1) && (a <= 10)) firstcode();
else if ((a 10) && (a <= 50)) secondcode();
else if (a == 800) thirdcode();
else defaultcode();
Too bad C didn't keep the range syntax from BCPL. Then you could
have used the even clearer:

if (1 <= a <= 10) firstcode();
else if (10 < a <= 50) secondcode();
else if (a == 800) thirdcode();
else defaultcode();

I disagree. The grammar needed to parse such constructs is a
horror, and the result is all sorts of silly errors. SPL (Algol
based HP System Programming Language for the HP3000) had that
construct, and it created nothing but trouble.
It could be done with a preprocessor for C. This needs a lot more work
before use in production code.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char *p, *q;
int pe, qe;
char line[1024];

while(fgets(line, sizeof line, stdin))
{
p = strstr(line, "<");
if(p)
{
q = strstr(p+1, "<");
if(q)
{
*p = 0;
*q = 0;
if(p[1] == '=') { pe = '='; p++; } else pe = ' ';
if(q[1] == '=') { qe = '='; q++; } else qe = ' ';
printf("%s<%c%s && %s<%c%s", line, pe, p+1, p+1, qe, q+1);
}
else
{
printf("%s", line);
}
}
else
{
printf("%s", line);
}
}
return 0;
}

Caveats: Only works once per line. Knows nothing of C syntax. Does not
detect comments or string literals.

Example:

C:\docs\prog\c>type test.c
#include <stdio.h>

void test(int a, int b, int c)
{
printf("%d lt %d lt %d = %d\n", a, b, c, a < b < c);
printf("%d lt %d le %d = %d\n", a, b, c, a < b <= c);
printf("%d le %d lt %d = %d\n", a, b, c, a <= b < c);
printf("%d le %d le %d = %d\n", a, b, c, a <= b <= c);
printf("\n");
}

int main(void)
{
test(1,2,2);

return 0;
}

C:\docs\prog\c>gcc -ansi -pedantic -Wall -W -O2 rangepp.c -o rangepp

C:\docs\prog\c>rangepp < test.c test2.c && gcc test2.c && a
1 lt 2 lt 2 = 0
1 lt 2 le 2 = 1
1 le 2 lt 2 = 0
1 le 2 le 2 = 1

--
Simon.
Sep 10 '06 #21

P: n/a
CBFalconer wrote:
sv***********@gmail.com wrote:
>>
CBFalconer wrote:
>>Why in heavens name use it and become non-portable, when the
portable code (following) is clearer:

if ((a >= 1) && (a <= 10)) firstcode();
else if ((a 10) && (a <= 50)) secondcode();
else if (a == 800) thirdcode();
else defaultcode();

Too bad C didn't keep the range syntax from BCPL. Then you could
have used the even clearer:

if (1 <= a <= 10) firstcode();
else if (10 < a <= 50) secondcode();
else if (a == 800) thirdcode();
else defaultcode();

I disagree. The grammar needed to parse such constructs is a
horror,
Not true. Why do you think this?

(The BCPL parser has something in the nature of a hack, but not
a nasty hack - the nasty bit was the code generation, which,
at least in the compiler I tinkered with, re-evaluated middle
expressions, so if they had side-effects URGH.

I've also implemented long relational expressions myself. The
grammar is peanuts. The tricky bit is just arranging to not
re-evaluate the middle expressions, and that's one of those
jobs where, once you know you have to do it, you just do it.)

--
Chris "Spice" Dollin
A rock is not a fact. A rock is a rock.

Sep 11 '06 #22

This discussion thread is closed

Replies have been disabled for this discussion.