Case Statement

marlin55
Posts: 15
Joined: Wed Feb 14, 2018 4:00 pm
My devices: iPad Pro + Windows PC
Flag: Great Britain

Case Statement

Post by marlin55 »

Is there a CASE statement or equivalent in smartBasic?

I'm looking to convert a Day number into it's text equivalent, something like:

SELECT CASE dayno
CASE 1
day$ = "Monday"
CASE 2
day$ = "Tuesday"
etc.

User avatar
Mr. Kibernetik
Site Admin
Posts: 4782
Joined: Mon Nov 19, 2012 10:16 pm
My devices: iPhone, iPad, MacBook
Location: Russia
Flag: Russia

Re: Case Statement

Post by Mr. Kibernetik »

No, there is not.
You need to use IF statement.

matt7
Posts: 115
Joined: Sun Jul 12, 2015 5:00 pm
My devices: iPhone
Location: USA

Re: Case Statement

Post by matt7 »

This is how I switch on a variable value. The main downside is that is a little messy and annoying to keep track of how many END IFs I need at the end, but the main reason to use this style is to avoid accumulating indents with each "ELSE IF".

Code: Select all

IF a = 1 THEN
  ' do something
ELSE ! IF a = 2 THEN
  ' do something
ELSE ! IF a = 3 THEN
  ' do something
ELSE
  ' default case
END IF ! END IF ! END IF
which is basically a condensed way of writing:

Code: Select all

IF a = 1 THEN
  ' do something
ELSE
  IF a = 2 THEN
    ' do something
  ELSE
    IF a = 3 THEN
      ' do something
    ELSE
      ' default case
    END IF
  END IF
END IF

matt7
Posts: 115
Joined: Sun Jul 12, 2015 5:00 pm
My devices: iPhone
Location: USA

Re: Case Statement

Post by matt7 »

Btw, you may have only used the dayno and day$ example to simplify your question for the forum, but for that specific example, using a string array would be much simpler than a case statement.

Code: Select all

OPTION BASE 1
DIM dayArr$(7)
dayArr$(1) = "Monday"
dayArr$(2) = "Tuesday"
dayArr$(3) = "Wednesday"
dayArr$(4) = "Thursday"
dayArr$(5) = "Friday"
dayArr$(6) = "Saturday"
dayArr$(7) = "Sunday"

' . . .

day$ = dayArr$(dayno)
Or alternatively a conversion function (note this example uses the default OPTION BASE 0, and the function handles converting the 1-based day number to the 0-based array index). This also lets you build in any input validation/error handling or other processing.

Code: Select all

day$ = DayNo2DayStr$(dayno)

DEF DayNo2DayStr$(dayno)
  IF init = 0
    DIM dayArr$(7)
    dayArr$(0) = "Monday"
    dayArr$(1) = "Tuesday"
    dayArr$(2) = "Wednesday"
    dayArr$(3) = "Thursday"
    dayArr$(4) = "Friday"
    dayArr$(5) = "Saturday"
    dayArr$(6) = "Sunday"
    init = 1
  END IF
  
  IF (dayno < 1) OR (dayno > 7) THEN
    RETURN ""    ' Error case
  ELSE
    RETURN dayArr$(dayno-1)
  END IF
END DEF

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Re: Case Statement

Post by Henko »

Lots of possibilities. I use this one:

Code: Select all

def nr2day$(nr)
  if nr=1 then return "Monday"
  if nr=2 then return "Tuesday"
  if nr=3 then return "Wednesday"
  if nr=4 then return "Thursday"
  if nr=5 then return "Friday"
  if nr=6 then return "Saturday"
  if nr=7 then return "Sunday"
  return ""
end def

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: Case Statement

Post by rbytes »

Yet another method:

Code: Select all

print today$(4)

def today$(sel)
  RESTORE
  FOR t=1 to 7
    READ tday$(t)
  NEXT t
  RETURN tday$(sel)
  DATA "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
END DEF
Note that the overhead of reading the data on each call is so small that I just restore rather than skipping it.


Here is a slight revision that reads the data only once.

Code: Select all

print today$(4)

def today$(sel)
  IF init THEN skip
  FOR t=1 to 7
    READ tday$(t)
  NEXT t
  init=1
  skip:
  RETURN tday$(sel)
  DATA "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
END DEF
I notice that in matt7's examples, the arrays are being dimensioned. That is not necessary in Smart Basic unless the array size is greater than 10.
The only thing that gets me down is gravity...

matt7
Posts: 115
Joined: Sun Jul 12, 2015 5:00 pm
My devices: iPhone
Location: USA

Re: Case Statement

Post by matt7 »

rbytes wrote:
Mon May 13, 2019 3:21 pm
I notice that in some of the previously posted examples, arrays smaller than 10 are being dimensioned. That is not necessary in Smart Basic.
True. I didn't even think about that, since I prefer to just DIM every array for clarity so that I know how many array elements I'm intending to use (a lot of the things I do are to help myself in the future when I look back at my code). Similar to your reasoning for just reading the DATA into the array every time, I see the overhead as negligible, especially since DIMs are only done once (mostly). But it's a good idea to point this fact out for anyone newer looking at our example code.

Anyway, all of the above examples are great if you only need to return one value or execute one line of code, but if you want multiple lines of code executed for each "case" then IF blocks (or GOTOs or GOSUBs) are needed. And speaking of GOTOs here is another alternative (supporting multiple lines like you would have with a SWITCH..CASE block):

Code: Select all

' switch_dayno
ON dayno GOTO d1, d2, d3, d4, d5, d6, d7
d1:
  day$ = "Monday"
  GOTO end_switch_dayno
d2:
  day$ = "Tuesday"
  GOTO end_switch_dayno

' etc . . .

end_switch_dayno:
The only thing you would have to be careful about here is not duplicating labels in your code (within any given scope). And a limitation of the ON GOTO syntax is that it only supports integers starting with 1.

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: Case Statement

Post by GeorgeMcGinn »

Hey Matt, I actually like this solution to an alternative for the CASE statement, except there's one problem – what happens if dayno is anything but 0 through 6?

This is great if that could never happen, but a true CSE statement will have a catchall or an else bucket for conditions that will never meet. Not always but most of the time you code in case statement for an ELSE condition.

I like it and will adopt it. Thanks.

matt7 wrote:
Mon May 13, 2019 3:50 pm
rbytes wrote:
Mon May 13, 2019 3:21 pm
I notice that in some of the previously posted examples, arrays smaller than 10 are being dimensioned. That is not necessary in Smart Basic.
True. I didn't even think about that, since I prefer to just DIM every array for clarity so that I know how many array elements I'm intending to use (a lot of the things I do are to help myself in the future when I look back at my code). Similar to your reasoning for just reading the DATA into the array every time, I see the overhead as negligible, especially since DIMs are only done once (mostly). But it's a good idea to point this fact out for anyone newer looking at our example code.

Anyway, all of the above examples are great if you only need to return one value or execute one line of code, but if you want multiple lines of code executed for each "case" then IF blocks (or GOTOs or GOSUBs) are needed. And speaking of GOTOs here is another alternative (supporting multiple lines like you would have with a SWITCH..CASE block):

Code: Select all

' switch_dayno
ON dayno GOTO d1, d2, d3, d4, d5, d6, d7
d1:
  day$ = "Monday"
  GOTO end_switch_dayno
d2:
  day$ = "Tuesday"
  GOTO end_switch_dayno

' etc . . .

end_switch_dayno:
The only thing you would have to be careful about here is not duplicating labels in your code (within any given scope). And a limitation of the ON GOTO syntax is that it only supports integers starting with 1.
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

matt7
Posts: 115
Joined: Sun Jul 12, 2015 5:00 pm
My devices: iPhone
Location: USA

Re: Case Statement

Post by matt7 »

GeorgeMcGinn wrote:
Wed May 15, 2019 3:00 am
what happens if dayno is anything but 0 through 6?
Good point. I don't use GOTOs and labels very often so it slipped my mind, but if you want to detect the error case you can right under the ON GOTO line. (In my earlier example without error handling, any "invalid" dayno would fall through to d1, causing day$ to be assigned "Monday" for any integer < 1 or > 7.)

Also note if dayno has a decimal value, the ON GOTO line ignores it. So dayno = 2.9 results in day$ being assigned "Tuesday".

Code: Select all

din:
INPUT "Enter day of the week (1-7)": dayno

' switch_dayno
ON dayno GOTO d1, d2, d3, d4, d5, d6, d7

' default case
  print "Bad dayno value! Must be 1-7."
  GOTO din

d1:
  day$ = "Monday"
  GOTO end_switch_dayno

d2:
  day$ = "Tuesday"
  GOTO end_switch_dayno

d3:
  day$ = "Wednesday"
  GOTO end_switch_dayno

d4:
  day$ = "Thursday"
  GOTO end_switch_dayno

d5:
  day$ = "Friday"
  GOTO end_switch_dayno

d6:
  day$ = "Saturday"
  GOTO end_switch_dayno

d7:
  day$ = "Sunday"
  GOTO end_switch_dayno

end_switch_dayno:

print "The day is " & day$
Though to match typical CASE..SWITCH convention where the default case is last you might want to do something like this:

Code: Select all

din:
INPUT "Enter day of the week (1-7)": dayno

' switch_dayno
ON dayno GOTO d1, d2, d3, d4, d5, d6, d7
GOTO ddef

d1:
  day$ = "Monday"
  GOTO end_switch_dayno
  
' . . .

ddef:  ' default case
  print "Bad dayno value! Must be 1-7."
  GOTO din
  
end_switch_dayno:

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Re: Case Statement

Post by Henko »

I would not do the error handling (printing a message) within the function, but only do the error checking and leave the handling to the calling program.

An obvious case : when the program is in the graphics mode, you will not have an error message.
Some of the examples given simply return an empty string in case of error. That seems the right thing.

Post Reply