[comp.lang.pascal] case

tpehrson@javelin.sim.es.com (Tim Clinkenpeel) (06/04/91)

so i can't use case for strings, eh?  what are my alternatives?  a list of
if-thens?  (tp5.0)

-- 
   /=============================/ 
  / tpehrson@javelin.sim.es.com /      i will work for food 
 /=====aka: tim clinkenpeel====/ 
[DISCLAIMER: send SASE to: disclaimer, 84151-0521]

eagle@garfield.catt.ncsu.edu (Daniel L'Hommedieu) (06/04/91)

tpehrson@javelin.sim.es.com (Tim Clinkenpeel) writes:
>so i can't use case for strings, eh?  what are my alternatives?  a list of
>if-thens?  (tp5.0)

I liked to use a single string of all of the possibilities, evenly
spaced.  That way, you can divide by the width of each entry (the same
for all) to then use a case.  For example (please forgive if I use "C"
grammar, because that's my primary language now):
  var possible,test:string;
      found:integer;
  begin
    possible="DIR  CLS  SET  MATCH";
      { notice that all are 5 wide! }
    test="SET";
    found=(pos(test,possible)/5);
    if (found<>0) then
      case found of
        1: begin /*perform stuff for DIR here*/ end;
        2: begin /*perform stuff for CLS here*/ end;
      ....

you get the picture, no doubt.

Daniel L'Hommedieu
eagle@catt.ncsu.edu
--
As the sweat poured down my forehead, I quickly glanced at the clock to
see how much longer I had to complete my exam.  The two hours left would
seem like days.  As each precious second passed, I decided I should make
up new math rules.  Two hours is enough to be creative, isn't it?

dm2368@eecs1.eecs.usma.edu (Fichten Mark CPT) (06/04/91)

> From: Tim Clinkenpeel <tpehrson@javelin.sim.es.com>
> 
> so i can't use case for strings, eh?  what are my alternatives?  a list of
> if-thens?  (tp5.0)
> 
Since the 'selecter' for a case statement MUST be of an ordinal type,
you can not use a string.  However, there are ways around this.  For
example, if I have a variable called NetworkType and it is a string, and
you only assign values like '3Com', 'Clarkson', 'Mine', etc., you can do
a case statement like this:

	case NetwordType[1] of
		'3'{Com}     : DoSomethingWith3Com;
		'C'{larkson} : DoSomethingWithClarkson;
		'M'{ine}     : DoSomethingWithMine;
	end;

Of course an enumerated type would work much better here but I hope
that you get the idea.  

Hope this helps...
____________________________________________________________________________

CPT Mark Fichten      | INTERNET: fichten@eecs1.eecs.usma.edu              |
Captain U.S. Army     |           @trotter.edu:dm2368@eecs1.eecs.usma.edu  |
                      | USENET:   rutgers.edu!trotter!eecs1!dm2368         |
                      |           harvard.edu!trotter!eecs1!dm2368         |
____________________________________________________________________________

g_harrison@vger.nsu.edu (George C. Harrison, Norfolk State University) (06/05/91)

In article <1991Jun3.222059.16125@javelin.sim.es.com>, tpehrson@javelin.sim.es.com (Tim Clinkenpeel) writes:
> so i can't use case for strings, eh?  what are my alternatives?  a list of
> if-thens?  (tp5.0)
> 
> -- 
>    /=============================/ 
>   / tpehrson@javelin.sim.es.com /      i will work for food 
>  /=====aka: tim clinkenpeel====/ 
> [DISCLAIMER: send SASE to: disclaimer, 84151-0521]

I'm not a TP expert, but Pascal (in general) does not allow nondiscrete types
in case statements.  STRING is definitely nondiscrete!  

A list of if-then's in not so bad if you structure them correctly.  After all
isn't that what case is all about?  As an alternative you may want to convert
the string or part thereof to an enumerated type and use a variable of that
type in the case statement; however, in general, this does not allow for
string's that don't conform to the type.

George...

-- George C. Harrison                              -----------------------
----- Professor of Computer Science                -----------------------
----- Norfolk State University                     -----------------------
----- 2401 Corprew Avenue, Norfolk, Virginia 23504 -----------------------
----- INTERNET:  g_harrison@vger.nsu.edu ---------------------------------

CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel) (06/05/91)

In article <1991Jun3.222059.16125@javelin.sim.es.com>,
  tpehrson@javelin.sim.es.com (Tim Clinkenpeel) writes:

>so i can't use case for strings, eh?  what are my alternatives?  a
>list of if-thens?  (tp5.0)

That's one option. Another is to test the strings against the
elements of an array, and use the matching index as the argument for
the case:

type
  strArray : array [1..5] of string[6];
const
  caseStrings : strArray =
    ('DELETE','INSERT','SORT','REPORT','QUIT');
var
  inputString : string[6];
  i : word;
begin
  GetInput(inputString);
  inputString := UpCaseString(inputString);
  i := 5;
  while (i > 0) and (inputString <> caseStrings[i]) do
    Dec(i);
  case i of
    0 : ; {no match}
    1 : procDelete;
    2 : procInsert;
    3 : procSort;
    4 : procReport;
    5 : Quit;
end.

If you have lengthy strings or many of them, or have other
objections to the "match the array" approach, then you can calculate
some type of value from the string (i.e., "hash" it) and use that
value as the case variable.

Cheers--                        --Karl

+====================================================================+
| Karl Brendel                           Centers for Disease Control |
| Internet: CDCKAB@EMUVM1.BITNET         Epidemiology Program Office |
| Bitnet: CDCKAB@EMUVM1                  Atlanta GA  30093       USA |
|                        Home of Epi Info 5.0                        |
+====================================================================+

jfr@locus.com (Jon Rosen) (06/05/91)

In article <1048.284bd1ff@vger.nsu.edu> g_harrison@vger.nsu.edu (George C. Harrison, Norfolk State University) writes:
>In article <1991Jun3.222059.16125@javelin.sim.es.com>, tpehrson@javelin.sim.es.com (Tim Clinkenpeel) writes:
>> so i can't use case for strings, eh?  what are my alternatives?  a list of
>> if-thens?  (tp5.0)
>I'm not a TP expert, but Pascal (in general) does not allow nondiscrete types
>in case statements.  STRING is definitely nondiscrete!  
>A list of if-then's in not so bad if you structure them correctly.  After all
>isn't that what case is all about?  As an alternative you may want to convert
>the string or part thereof to an enumerated type and use a variable of that
>type in the case statement; however, in general, this does not allow for
>string's that don't conform to the type.

Ain't that a drag!  When, oh when, will compiler writers and language
designers of the Pascal/C mentality wake up and recognize that STRINGS
are indeed atomic (i.e., discreet) data types that deserve to be 
handled the same way integers, floats and bits are... Oh, I know,
STRINGS are not REALLY atomic with respect to the underlying processor...
But who cares?  Neither are sets, but Pascal has a defined fundamental
data type for sets...  Long integers are not defined on many 16-bit 
processors but nobody has ever suggested that C programmers ought to
write their own functions to handle long integer math!  No, this is
a real drag that is only partially remedied with languages like C++
where you can do most of what you want to do to make STRINGs a real
data type... However, you still can not coerce the compiler itself
to adapt all the semantics of your STRING class... In some Pascals
(particularly IBM's VS Pascal and Turbo), the CASE statement can be
optimized into a jump table in some cases where the range of values
is limited... this is easy to check for since only limited range
base types are allowed (Integer, enumerated, Char... Floats are also
prohibited)... However when the jump table option is not used, the
CASE statement turns into a good ole IF-THEN-ELSE internally...
Why, then oh why, can't Pascal be defined to allow any type...
If it is a limited range type, the jump option is still available...
Otherwise, no harm is done and the program looks much neater (and
is easier to write)...  BTW, PL/I supports the use of ANY data type
as the object of a SELECT statement (similar to the CASE/SWITCH
statements of PASCAL and C)...
 
Jon Rosen

jordan@aero.org (Larry M. Jordan) (06/06/91)

What's the big deal?  How about a hash table of (name,value) pairs?

  case hash_table.get_value(name) of
    {acceptable labels}
  end;

Where get_value returns the value part of the association.

Seems simple enough.

--Larry

phys169@csc.canterbury.ac.nz (06/06/91)

In article <1991Jun4.012145.8522@ncsu.edu>, eagle@garfield.catt.ncsu.edu (Daniel L'Hommedieu) writes:
> tpehrson@javelin.sim.es.com (Tim Clinkenpeel) writes:
>>so i can't use case for strings, eh?  what are my alternatives?  a list of
>>if-thens?  (tp5.0)
> 
> I liked to use a single string of all of the possibilities, evenly
> spaced. 

You can use variable-length fields, separated by a delimiter, e.g.

const Possible : string = 'CLARKSON,3COM,SNEAKER';

case pos(Net+',',Possible) of
     1 : DoClarksonStuff;
    10 : Do3ComStuff;
    15 : DoSneakerStuff;
    else writeln('Invalid! Choose from: ',Possible);
     end {of case};

You have to be careful with counting, though. I wish Pascal allowed such case
statements. I think TP3 did (Can anyone confirm this?). I used to think the
reason was it generated code to index an array of labels (which would be
very fast), but at least Turbo Pascal 5 doesn't - it does a series of tests,
which would adapt well to strings, surely.

By the way, be careful with...
>     possible="DIR  CLS  SET  MATCH";
>       { notice that all are 5 wide! }
>     test="SET";
>     found=(pos(test,possible)/5);
>     if (found<>0) then
>       case found of
>         1: begin /*perform stuff for DIR here*/ end;
>         2: begin /*perform stuff for CLS here*/ end;

because (a) you really need something like: possible:='    DIR  CLS  SET etc'
                         notice the leading spaces.......^ 
            or you need: found:=(pos(test,possible)+4) div 5);
        (b) watch out for small words being found in larger words earlier in
            the list, e.g. if you have 'RESET' and 'SET' as valid options, you
            must make sure 'SET' comes first in the list!
        (c) the method doesn't do a good job of spotting invalid input, where
            the input happens to be a substring of a valid alternative; that
            could be an advantage if you want to allow abbreviations, of course,
            but you may prefer a series of IF-THEN-ELSE tests, or writing a
            function that looks up a list. That would be required in any case
            if your list is larger than 255 bytes. What you choose then depends
            on the type of application - e.g. if you know the word is
            definately in a certain list one method may be more efficient; if
            all options in the list are unique within their first 3 letters 
            another may be better. You could argue that the Pascal language is
            doing us a favour in requiring the programmer to choose the method,
            rather than have the compiler always choose. 

Hope this helps,
Mark Aitchison, Physics, University of Canterbury, New Zealand.

milne@ics.uci.edu (Alastair Milne) (06/08/91)

In <1048.284bd1ff@vger.nsu.edu> g_harrison@vger.nsu.edu (George C. Harrison, Norfolk State University) writes:

>In article <1991Jun3.222059.16125@javelin.sim.es.com>, tpehrson@javelin.sim.es.com (Tim Clinkenpeel) writes:
>> so i can't use case for strings, eh?  what are my alternatives?  a list of
>> if-thens?  (tp5.0)

>A list of if-then's in not so bad if you structure them correctly.  After all
>isn't that what case is all about?  

   Often not.  Turbo may implement them this way -- it's stepping during
   debugging seems to say so -- but jump tables are a preferred way
   if their size for the indexes of the give table is not prohibitive.
   A clever compiler will use an optimal mix of conditional jumps 
   and jump tables.

>As an alternative you may want to convert
>the string or part thereof to an enumerated type and use a variable of that
>type in the case statement; however, in general, this does not allow for
>string's that don't conform to the type.

   As in ...

   ** a hash function **

   The good part is it can be pretty quick conversion, depending on
   what function you use, and it frees you from playing games with
   the lengths of the strings you will be using.

   The bad part is you have to deal with hash collisions, either by 
   using a function specialised to the set of strings you know you
   will have, or by more iterative hash resolution techniques.
   A full hash table is probably a good idea.  If you record, with each
   string you're prepared to recognise, an enumeration that identifies 
   it, it becomes very easy just to return the enumerated value (including
   one for "none", of course) and index the case on that.


   Alastair Milne

Harold.Ruby@farwest.FidoNet.Org (Harold Ruby) (06/08/91)

on 6 Jun 91 11:26:01 -Unknown- said to All
 >You have to be careful with counting, though. I wish Pascal 
 >allowed such case
 >statements. I think TP3 did (Can anyone confirm this?). I used 
 >to think the
 >reason was it generated code to index an array of labels (which 
 >would be
 >very fast), but at least Turbo Pascal 5 doesn't - it does a 
 >series of tests,
 >which would adapt well to strings, surely.
 >
 >By the way, be careful with...
 >>     possible="DIR  CLS  SET  MATCH";
 >>       { notice that all are 5 wide! }
 >>     test="SET";
 >>     found=(pos(test,possible)/5);
 >>     if (found<>0) then
 >>       case found of
 >>         1: begin /*perform stuff for DIR here*/ end;
 >>         2: begin /*perform stuff for CLS here*/ end;
 >
 >because (a) you really need something like: possible:='    

    Actually, you have to be careful with your example as well:

on 6 Jun 91 11:26:01 -Unknown- said to All
 >const Possible : string = 'CLARKSON,3COM,SNEAKER';
 >
 >case pos(Net+',',Possible) of
 >     1 : DoClarksonStuff;
 >    10 : Do3ComStuff;
 >    15 : DoSneakerStuff;
 >    else writeln('Invalid! Choose from: ',Possible);
 >     end {of case};

    Cont Possible : string = 'CLARKSON,3COM,SNEAKER,';
                            Note the comma --------^

If you're going to check for a "case pos(net+',',Possible)" you need that  
comma or poor sneaker will never see the light.. 

Harold

 * Origin: !/\/\egalon (1:106/1999)

Kai_Henningsen@ms.maus.de (Kai Henningsen) (06/09/91)

phys169%csc.canterbury.ac.nz @ SUB schrieb am Mi 05.06.1991, 21:26

pc>const Possible : string = 'CLARKSON,3COM,SNEAKER';
pc>
pc>case pos(Net+',',Possible) of

Oops. Standard error! Try this:

const Possible : string = 'CLARKSON,3COM,SNEAKER,';
                                                ^
- or you won't ever recognize SNEAKER ...
--
Kai Henningsen  Internet: kh@ms.maus.de
Muenster         UUCP: any_backbone_that_knows_domains!ms.maus.de!kh
Germany         Fido: kh%maus ms, 2:242/2.6 or Kai Henningsen, 2:242/2.244