Variable type in MapBasic

1,497 views
Skip to first unread message

Matt

unread,
Feb 5, 2007, 7:33:24 PM2/5/07
to MapInfo-L
Hello all,

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

Bill Thoen

unread,
Feb 5, 2007, 8:00:02 PM2/5/07
to mapi...@googlegroups.com

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

jakes

unread,
Feb 5, 2007, 10:50:12 PM2/5/07
to MapInfo-L
You simply have to look at your DIM and GLOBAL statements to find the
type of the variable you are looking for; in mapBasic, a variable does
not exist without such defintion. But it is not what you are asking
for, is it? It would be too simple.

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.


Matt

unread,
Feb 6, 2007, 8:22:17 PM2/6/07
to MapInfo-L
Thank you for your answers, but I don't think I explained myself
correctly.

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

Terry McDonnell

unread,
Feb 7, 2007, 5:10:00 AM2/7/07
to mapi...@googlegroups.com
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

Matt

unread,
Feb 7, 2007, 8:12:14 PM2/7/07
to MapInfo-L
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 -

jakes

unread,
Feb 7, 2007, 10:46:56 PM2/7/07
to MapInfo-L
The only way to have a foolproof numerical input with edittext I know
is to write a specific function that will read the string provided by
edittext (into variable should be string not float) to check then to
check each of its characters for its validity. The first character can
be the plus or minus sign, a period (as decimal separator) or a digit.
The following ones can be digits or a period (but only one allowed in
all the string). When this test is successfull, the function is "true"
and returns in an output argument the value given by VAL(good_chain).
If the test fails, the function is "false" and any value can be
returned but should not be processed. You can then cycle the dialog
until an acceptable value is entered.

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.

SCISOFT

unread,
Feb 8, 2007, 12:07:32 AM2/8/07
to mapi...@googlegroups.com
As I understand it, it is a textbox without any means of input verification
unless you write it yourself - as the reply by JP indicates.

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

Warren Vick, Europa Technologies Ltd.

unread,
Feb 8, 2007, 4:10:27 AM2/8/07
to mapi...@googlegroups.com
Hello Matt,

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

Terry McDonnell

unread,
Feb 8, 2007, 5:28:35 AM2/8/07
to mapi...@googlegroups.com
Matt

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.

Spencer Simpson

unread,
Feb 8, 2007, 9:28:03 AM2/8/07
to mapi...@googlegroups.com
Long ago, I gave up using Into clauses in MapBasic dialog Edit controls.
They are simply too limited for anything but the simplest dialogs.

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 Pilkington

unread,
Feb 8, 2007, 1:56:34 PM2/8/07
to mapi...@googlegroups.com
Spencer seems to have the right idea. There was chat about 4 years ago, or
so, about reading in variable input. If the val() function produces a zero,
it is either a real zero or a typo... use revert dialog. Note that on
edittext inputs you can't do a check until you hit the okbutton, or a
special button to check input. Mapinfo itself is incapable of setting up a
dialog for reading integers... don't use DMS input for degree values of 0
but positive minutes, ie 0 15 00. It will move it to -.25 degrees. Let this
be a lesson about handling data input.

Tony

Mark Mclean

unread,
Feb 8, 2007, 2:17:03 PM2/8/07
to mapi...@googlegroups.com

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

Terry McDonnell

unread,
Feb 9, 2007, 6:36:07 AM2/9/07
to mapi...@googlegroups.com
Matt

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

Reply all
Reply to author
Forward
0 new messages