Case Statement
Case Statement
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.
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.
- Mr. Kibernetik
- Site Admin
- Posts: 4786
- Joined: Mon Nov 19, 2012 10:16 pm
- My devices: iPhone, iPad, MacBook
- Location: Russia
- Flag:
Re: Case Statement
No, there is not.
You need to use IF statement.
You need to use IF statement.
Re: Case Statement
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".
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
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
Re: Case Statement
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.
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
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)
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
-
- Posts: 814
- Joined: Tue Apr 09, 2013 12:23 pm
- My devices: iPhone,iPad
Windows - Location: Groningen, Netherlands
- Flag:
Re: Case Statement
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
- 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:
- Contact:
Re: Case Statement
Yet another method:
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.
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.
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
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
The only thing that gets me down is gravity...
Re: Case Statement
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:
- 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:
- Contact:
Re: Case Statement
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.
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 pmTrue. 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):
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.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:
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)
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)
Re: Case Statement
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$
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:
-
- Posts: 814
- Joined: Tue Apr 09, 2013 12:23 pm
- My devices: iPhone,iPad
Windows - Location: Groningen, Netherlands
- Flag:
Re: Case Statement
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.
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.