I am implementing some error checking into one of my MapBasic
projects, and was wondering if there is a function to return the type
of a specific variable. I have searched through the MapBasic
reference, to no avail.
I thought a function like this would be pretty important in a language
like MapBasic...
Are there any suggestions as to what else I can do?
Matt
MapBasic doesn't have strong typing and there's no function that returns a
variable's type. You can literally do silly things like this:
dim str as string
dim num as integer
str = 42
num = "23_skkidoo"
and you will find that str contains "42" and num = 23!
The solution is defensive programming. Adopt a convention for variable
names where the name of the variable tells you the type. I use a convention
where I prefix every non-trivial variable with a naming code that tells me
the type I intend for the variable. It looks like this:
sVar string
iVar smallint
nVar integer
fVar float
objVar object
aVar alias
dVar date
bVal logical (boolean)
tVar user defined type
Module scope variables get a m_ prefix, as the module scope integer
variable m_nVar. Application scope (global) variables get a g_ prefix as in
the global string variable g_sVar.
For common counter and string index variables, I just use i, j, k, and p
and q. The scope of these variables should be pretty tight so they're
easier to keep track of.
Use your favorite convention, but you really ought to havæ one for all but
the most trivial programs. The Holy Grail you're looking for is
self-documenting code (if there is such a thing!)
- Bill Thoen
In error checking, you may want to find if some data you read in is of
the proper type (all digits, all character etc,,). In that case you
are not asking about variable types but about data. Did I understand
your question correctly? If yes, I do not know about such a function;
I had to develop my own tools when checking for the acceptability of
data input into some edittext control before accepting it for
processing and it was not a total success.
The original problem more relates to error checking dialog input from
the user. For example, I have a dialog box that has two EditText
controls, one for latitude and one for longitude. Unfortunately,
because MapBasic doesn't have very extensive dialog attributes, users
can input any text they would like in the controls.
I guess a "variable" type function would be useless in this case
anyway, as EditText's always return strings. Perhaps I should be using
the Val() function and errorchecking past that.
I think I just solved my problems.
Regards,
Matt
AFAIK Edittext controls store the input into a string OR numeric var.
Depends how you DIM the var that goes in the INTO clause of the edittext
declaration.
Terry
Therein lies my problem. I Dim a variable to be a Float, for example,
and then get an EditText control to assign a value to it. If the user
doesn't input a numeric value, then MapBasic throws an error? How can
I catch this BEFORE the error is thrown?
Matt
> Matt- Hide quoted text -
>
> - Show quoted text -
There are other considerations: 1 - VAL() will accept only a period as
decimal separator even if the Windows parameters are set on a comma.
Thus warn the user about that, if it does not get it right. Or your
function can convert it into a period. 2 - VAL() does not accept
internal spaces as thousand separator. Your function could accept
those blanks (any blanks as a matter of fact) by simply packing the
string as they are encountered. 3 - I am not sure that VAL() will
accept a plus sign; it is indeed not necessary; your function should
drop it when it is found.
This wil make a lot of wordy code for such a fundamental need.
Once a series of suitable functions have been written, you can of course
re-use them in the next MBX you need to construct that needs user input
verification.
A way around this is to write a part of what you want to do using
'Integrated Mapping' (for example, with Visual Basic). It may be possible
for you to verify the user input, and then pass that to MapInfo
Professional.
Of course that is not always feasible.
The 'external' languages often have a better user interface (forms,
verification of input, etc) and also the UI is easier to construct (unless
you use Trey Patillo's MB-Coder.
IL Thomas
GeoSciSoft - Perth, Australia
-----Original Message-----
From: mapi...@googlegroups.com [mailto:mapi...@googlegroups.com] On
Behalf Of jakes
Sent: Thursday, February 08, 2007 12:47 PM
To: MapInfo-L
Subject: [MI-L] Re: Variable type in MapBasic
The best way to control user input is to always drop into string variables
(effectively the lowest common denominator in basic data types) and then do
your own checking on it before casting to the desired variable type
(integer, float, date, etc.).
Regards,
Warren Vick
Europa Technologies Ltd.
http://www.europa-tech.com
Hmmm, rather than my helping you it turns out now that you've presented
ME with a problem :-) I'd never considered that, and I only have a few
dialogues that read a numeric input (most select from a combo). But I've
just looked at one where I expect a number, entered alpha and got an
error. I guess, as I've been fairly new to MB when I wrote the sys, and
used to VFP, I'd assumed input to a numeric var would auto. be
restricted to such. Now I know that's not the case.
So it looks like I'll have to revisit my code and face the same problem.
I think Jake's suggestion is the way to go, inputting to a text string,
then parsing it, char by char, using INSTR() and ASC() to ascertain
whether each char is in number range (ASCII values 48-57), "." (46),
SPACE (32), etc., throwing up an error message if not, and using VAL()
to convert a valid input to a numeric, which is the output from the
function.
Off to look at this myself now.
Instead, I write a handler for the OKButton, and validate all of the
dialog's EditText controls there. I Dim module-level variables, dedicated to
the dialog (their names usually begin with "dlg_"), to hold the validated
values.
A dialog USUALLY corresponds to a function returning a Logical (sometimes a
smallint if the dialog has a MultiListBox). If the dialog returns
CommandInfo (CMD_INFO_DLG_OK), the function copies the validated values into
the function's output parameters, and returns TRUE (or the number of items
selected). Otherwise, it returns FALSE (or 0).
This way:
- I get to present the user with my own error messages, which are more
likely to tell users where they went wrong.
- Since the dialog is preserved if there was an error, users get a chance to
enter correct values.
- Since I'm using variables dedicated to the dialog, I don't write over
anything vital if the first three controls have correct values and the
fourth doesn't.
Hope this helps
Spencer
Tony
It would be nice if MB had something similar to the old VB
keypress event as shown below :
'Ensuring non-numeric
input
Private Sub
InputBox_KeyPress(KeyAscii As
Integer)
If ((KeyAscii > = Asc("0")) And
(KeyAscii <= Asc("9"))) Then KeyAscii =
0
End Sub
'Ensuring numeric
input
Private Sub
InputBox_KeyPress(KeyAscii As
Integer)
If ((KeyAscii < Asc("0")) Or
(KeyAscii > Asc("9"))) Then KeyAscii =
0
End Sub
These check each
character as it is typed and ignore/disallow invalid ones.
Cheers,
Mark
In case you haven't solved the problem, here is a soln. I've come up
with. As I said, I hadn't suspected the fallibility of text controls
and hadn't tested my original. So I made the recipient var a string,
instead of numeric. The existing OK button handler, I now have calling
the function VALIDATE_INTEGER.
Note, this only tests for an integer numeric. For a real, the test on
lnAscVal will have to include checks for the ASCII values of these too.
I hope this is of help
Terry
'________________________________________________
Sub SET_WALK_SPEED_DIALOG
' _______________________
Dim lcWalkSpeed as String
DIALOG
Title "Set Walking Speed for Stop Isochrone Calculations"
Width 240
Control StaticText
Title "Walking Speed (in Km/H)"
Control EditText
ID WSPEED_DLOG_EDITEXT_ID
Width 20
Into lcWalkSpeed
Value STR$( gnWalkSpeed)
Control OKButton
ID WSPEED_DLOG_OK_BUTTON_ID
Calling VALIDATE_WALK_SPEED
Control CancelButton
End Sub
'________________________________________________
Sub VALIDATE_WALK_SPEED
' _____________________
Dim lnWalkSpeed as SmallInt,
lcWalkSpeed as String
lcWalkSpeed = ReadControlValue( WSPEED_DLOG_EDITEXT_ID)
If not VALIDATE_INTEGER( lcWalkSpeed) then
Dialog Preserve
Else
lnWalkSpeed = VAL( lcWalkSpeed)
If lnWalkSpeed >= 20
Or lnWalkSpeed < 1 then
Note "Walking speed must be between 1 and 20 Km/H"
Dialog Preserve
Else
gnWalkSPeed = lnWalkSpeed
End If
End If
End Sub
'________________________________________________
Function VALIDATE_INTEGER( ByVal tcNumString as String) as Logical
' _______________________
Dim lnLenString, lnCharNum, lnAscVal as SmallInt,
lcString, lcChar as String,
llNumeric as Logical
lcString = RTRIM$( tcNumString)
lnLenString = LEN( lcString)
llNumeric = TRUE
lnCharNum = 1
Do while lnCharNum <= lnLenString
and llNumeric
lcChar = MID$( lcString, lnCharNum, 1)
lnAscVal = ASC( lcChar)
If lnAscVal < 48
Or lnAscVal > 57 then
llNumeric = FALSE
Else
lnCharNum = lnCharNum + 1
End If
Loop
If not llNumeric then
Note "You have not entered an integer value."
End If
VALIDATE_INTEGER = llNumeric
End Function