Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

switch { } - case for range

3 views
Skip to first unread message

markpapadakis

unread,
Sep 6, 2006, 1:40:12 PM9/6/06
to

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

Ben Pfaff

unread,
Sep 6, 2006, 1:44:35 PM9/6/06
to
"markpapadakis" <markpa...@gmail.com> writes:

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

BRG

unread,
Sep 6, 2006, 1:54:44 PM9/6/06
to

This doesn't work with VC++ version 8 and I don't recall it working on
earlier versions either.

Brian Gladman

Robert Gamble

unread,
Sep 6, 2006, 2:00:33 PM9/6/06
to
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

markpapadakis

unread,
Sep 6, 2006, 2:08:20 PM9/6/06
to

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.

Clark S. Cox III

unread,
Sep 6, 2006, 2:12:20 PM9/6/06
to
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
clar...@gmail.com

jacob navia

unread,
Sep 6, 2006, 4:09:45 PM9/6/06
to

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

Mark McIntyre

unread,
Sep 6, 2006, 5:30:33 PM9/6/06
to
On Wed, 06 Sep 2006 22:09:45 +0200, in comp.lang.c , jacob navia
<ja...@jacob.remcomp.fr> wrote:

>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

markpapadakis

unread,
Sep 6, 2006, 5:34:31 PM9/6/06
to


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

CBFalconer

unread,
Sep 6, 2006, 11:50:25 PM9/6/06
to
> 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>


Richard Tobin

unread,
Sep 7, 2006, 8:01:14 AM9/7/06
to
In article <44FF9701...@yahoo.com>,
CBFalconer <cbfal...@maineline.net> 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();

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

Eric Sosman

unread,
Sep 7, 2006, 12:26:04 PM9/7/06
to

Richard Tobin wrote On 09/07/06 08:01,:

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.

--
Eric....@sun.com

Richard Tobin

unread,
Sep 7, 2006, 2:11:20 PM9/7/06
to
In article <1157646365.318129@news1nwk>,
Eric Sosman <Eric....@sun.com> wrote:

> 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

Mark McIntyre

unread,
Sep 7, 2006, 4:22:25 PM9/7/06
to
On 7 Sep 2006 12:01:14 GMT, in comp.lang.c , ric...@cogsci.ed.ac.uk
(Richard Tobin) wrote:

I would submit that the algo was probably flawed, if you found
yourself in this situation.

Richard Tobin

unread,
Sep 7, 2006, 6:08:47 PM9/7/06
to
In article <8qv0g21qf8i9vnusj...@4ax.com>,
Mark McIntyre <markmc...@spamcop.net> wrote:

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

boa

unread,
Sep 8, 2006, 12:49:25 AM9/8/06
to
* Richard Tobin wrote, On 07.09.2006 23:08:
[snip]

> case 0x10000...0xEFFF:

Shouldn't that be 0xEFFFF?

Boa

sven.a...@gmail.com

unread,
Sep 8, 2006, 10:49:21 AM9/8/06
to
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

CBFalconer

unread,
Sep 8, 2006, 12:10:42 PM9/8/06
to

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


Mark McIntyre

unread,
Sep 8, 2006, 5:45:39 PM9/8/06
to
On 7 Sep 2006 22:08:47 GMT, in comp.lang.c , ric...@cogsci.ed.ac.uk
(Richard Tobin) wrote:

>In article <8qv0g21qf8i9vnusj...@4ax.com>,
>Mark McIntyre <markmc...@spamcop.net> wrote:
>
>>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.

Richard Tobin

unread,
Sep 8, 2006, 8:09:36 PM9/8/06
to
In article <9to3g216brh02761o...@4ax.com>,
Mark McIntyre <markmc...@spamcop.net> wrote:

>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

Simon Biber

unread,
Sep 10, 2006, 8:03:26 AM9/10/06
to
CBFalconer wrote:
> sven.a...@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.

Chris Dollin

unread,
Sep 11, 2006, 6:11:08 AM9/11/06
to
CBFalconer wrote:

> sven.a...@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.

0 new messages