GIS制图实习六.docx
《GIS制图实习六.docx》由会员分享,可在线阅读,更多相关《GIS制图实习六.docx(17页珍藏版)》请在冰豆网上搜索。
GIS制图实习六
实习六MapBasic入门
武汉大学资源与环境科学学院 程雄王坤
一.MapBasic编程基础
1.MapBasic的基本语法规则
1.MapBasic的注释行:
用英文单引号“’”来标记注释语句。
2.程序中可以用大写、小写或混合的方式输入程序。
3.当一条语句超过一行所允许的长度时,可以把一个语句分成两行或多行书写。
4.通过Define语句可以定义一个标识符,它等价于一个特殊的值。
例如:
DefineMY_COLORl6711680
Mapbasic.def中用Define语句定义了许多标准MapBasic的标识符。
其中包括许多常用的颜色(例如BLACK,WHITE,RED,GREEN,BLUE,CYAN,MAGENTA和YELLOW)和其他标识符(例如TRUE,FALSE,RED,GREEN,BLUE和TAB_INF_NAME等),只要在程序开头一般需要输入下语句,就可以任意地使用这些标识符了:
Include“mapbasic.def”
5.Include语句的语法:
Include“filename”
这里filename是一个包含有MapBasic语句的文本文件。
Filename还可以包括一个目录路径。
如果没有指定路径,则编译器在当前工作目录寻找该文件,如果没有发现,则编译器又会在MapBasic安装目录下寻找。
Mapbasic.def中用Define语句定义了许多标准MapBasic的标识符(例如TRUE,FALSE,RED,GREEN,BLUE和TAB_INF_NAME等)。
当开发了越来越多的MgpBasic程序时,会发现某些代码会经常重复使用。
就可以写了一个或多个用户函数库(放到一个单独的文本文件中),如果在写的某个MapBasic程序中要使用这些用户函数,可以用Include调用这些用户函数,比如把该文件取名为functs.mb,可以用下面的语句把该函数库合并到程序中:
Include “functs.mb”
2.常量
MapBasic的常量有:
字符串常量、数值常量、逻辑常量、日期型常量等。
(1)字符串常量:
用两个英文双引号括起来表示的,双引号不是字符串的一部分,字符串常量最长可以有65535个字符。
(2)数值常量:
数值常量又分为整型常数(整型常量)和实型常数(实型常量)。
(3)逻辑常量:
逻辑常量只有两个值TRUE和FALSE。
TRUE为1,FALSE为0。
(4)日期型常量:
2003年12月31日可以用两种方法表示。
用八位整数“YYYYMMDD”表示,如20031231。
也可以用一个字符串表达式“MM/DD/YYYY”表示,如12/31/2003。
3.变量
MapBasic的变量分为全局变量和局部变量。
全局变量在程序中的任何过程中使用。
局部变量只能在定义它的函数或过程中使用。
因此,应该尽量使用局部变量。
MapBasic关于变量说明及变量赋值的语法规则与其他现代BASIC语言类似。
但是,MapBasic比其他BASIC语言支持更多的变量类型。
(1)每个变量名必须以字母、下划线“_”或者“~”号开头,后面可跟字母、数字、下划线“_”和“#”,变量名最多可以包含31个字符。
不能用MapBasic的关键词作为变量名。
(2)MapBasic支持以下类型变量,其中包括数值类型、字符类型、对象类型、逻辑型、日期型和样式类型等。
MapBasic的变量类型如下:
变量类型
描述及例子
SmallInt
范围在-32767~+32767之间的整数,用两个字节存储
Integer
范围在-2,147,483,647~+2,147,483,647之间的整数,用四个字节存储
Float
浮点数,用八个字节的IEEE格式存储
String
变长字符串,最多可有32767个字符
String*n
定长字符串,n为字符串长度(最多可有32767个字符)
Logical
逻辑值TRUE或FALSE,用两个字节存放(O为FALSE,非0为TRUE)
Date
日期型(MM/DD/YYYY),其中两个字节存放年,另两个字节存放月和日
Object
图形对象,如点(Point)、线(Line)、区域(Region)等
Pen
线型,如hwypen=MakePen(1,3,BLACK)
Brush
填充模式,如zbrush=MakeBrush(5,BLUE,WHITE)
Font
字体,如lbl_font=MakeFont(“Helv”,1,20,BLACK,WHITE)
Symbol
点符号
(3)程序中使用的变量都要先声明,然后才能使用,并且要保证声明的类型正确。
Dim语句用来声明局部变量。
Dim语句的语法形式如下:
Dim var_name[,ver_name,……]Asvar_type
[,var_name[,ver_name,……]Asvar_type]
Global语句用来声明全局变量,其用法和Dim语句相同。
为了便于管理全局变量,可以建立一个定义文件(Globals.def),并在该文件中定义全局变量,然后在程序中用Include语句将全局变量添加到程序中。
(4)MapBasic中只能定义一维数组变量,定义数组变量的方法是在变量后面加一对圆括号,圆括号中设定数组长度。
如果在定义数组变量时,没有定义大小则不能赋值,必须用ReDim重新定义大小后才能使用。
Dimcode()AsString,IAsInteger ‘定义数组变量Code和整型变量I
ReDimcode(10)AsString ‘定义数组变量Code的大小
I=Ubound(code) ‘获得数组长度10
ReDimcode(I+10) ‘数组长度增加到20
(5)用Type…EndType语句可以定义一个用户数据类型(CustomDateTypes)。
用户数据类型是一个或多个常规变量类型的组。
一般情况下,把Type…EndType放在程序的开始处。
如下例,定义了一个用户数据类型employee,然后把变量manager,staff(10),声明为employee类型,并给变量manager赋值:
Typeemployee
name AsString
title AsString
id ASInteger
EndType
Dim manager,staff(10) As employee
manager.name=“Joe”
manager.title=“DirectorofPublications”
manager.id=111223333
4.表达式
表达式是由一个或多个常量、变量、函数、表和运算符组成的式子。
表达式即可以简单到用一个常量表达,也可以由多个变量、常量、函数、表和操作符组成。
5.运算符
运算符是作用于一个或多个常量、变量或其他值,从而产生一个结果,它的表达形式可以是一个特殊的字符(如+、*、>)、一个词(如:
And、Or、Not)或者是一个词组(如:
ContainsPart、EntirelyWithin)。
在MapBasic中,运算符报括算术运算符、字符串运算符、日期运算符、比较运算符、逻辑运算符、地理运算符。
①.算术运算符:
常用的有:
+(加法)、-(减法)、*(乘法)、/(除法)、\(整除)、Mod(取余)、^(乘方)。
②.字符串运算符:
常用的有:
+、&、Like。
其中:
“+”和“&”运算符可以把两个或多个字符串表达式连接成一个更长的字符串表达式。
“Like”运算符执行字符串的比较。
字符串可以含有通配符“_”,和“%”,其中下划线“_”,表示任意一个字符,而百分号“%”表示任意一个或多个连续字符。
③.日期运算符:
常用的有:
加号“+”和减号“-”。
一个日期型值加上(或减去)一个整数,将返回一个日期型值,表示该日期以后(或之前)的一个日期。
两个日期型值相减将返回一个整型值,表示两个日期之间相隔的天数。
下面的例子用CurDate()函数确定当前的日期,然后计算出明天的日期tomorrow,一星期后的日期one_week_late以及今天是今年的第几天days_elapsed
Dim today,tomorrow,next_day AsDate,
Days_elpsedAsInteger
today=CurDate()
tomorrow=today+1
next_day=today+7
days_elapsed=today–StringToDate(“1/1”)
④.比较运算符:
常用的有:
=、<>、<、>、<=、>=、Between…And…
比较运算符通过比较两个相同类型的项产生一个逻辑值,TRUE或FASLE。
⑤.逻辑运算符:
逻辑运算符对两个逻辑值进行运算,结果仍产生一个逻辑值。
常用的有以下三种:
And、Or、Not
⑥.地理运算符:
在MapBasci中,可以使用下列地理运算符对表对象运算,其结果是产生一个逻辑值。
运算符 返回TRUE的情况
Contains 第一个对象包含第二个对象的中心
ContainsPart 第一个对象包含第二个对象的部分
ContinsEntire 第—个对象包含第二个对象的全部
Within 第一对象的中心在第二个对象中
PartlyWithin 第一个对象的部分在第二个对象中
EntirelyWithin 第一个对象全部在第二个对象中
Intersects 两个对象相交
⑦.运算符的优先级就是指在一个包含多个运算符的复杂表达式中,决定哪一个运算符优先被执行。
MapBasic对每一个运算符的优先级进行了规定,在同一行中的运算符的优先级顺序是:
最高优先级:
圆括号()
乘方^
*,/,Mod,\
+,-,字符串连接(+,&)
地理运算符,比较运算符,Like
Not
And
最低优先级:
Or
当一个表达式中有多个运算符时,优先级高的先处理,优先级低的后处理。
一般地,优先级相同的运算符从左到右依次处理,但对于乘方(A),是从右向左运算。
例如:
赋值语句x=2^2^3给变量x赋的值是256而不是64。
6.流程控制结构
流控制结构语句将影响到程序中语句的执行顺序,MapBasic主要有以下三种类型的流控制结构语句:
(1).分支语句(IF...Then、GoTo、DoCase)
①.If...Then语句的语法如下:
Ifif_conditionThen
If_statement_list
[ElseIfelseif_conditionThen
elseif_statement_list]
[ElseIf……]
[Else
else_statement_list]
[Endif]
②Do...Case语句的语法如下:
Do...Case do_condition
Case Case_expr
statement_list
[Case……]
[CaseElse
statement_list]
EndCase
③GoTo语句
在MapBasic程序运行时,GoTo语句可将跳转到程序中指定的标号行,执行该标号行后的语句,也可以返回到原来的位置执行。
GoTo语句要指定一个标号。
这个标号必须是在同一过程中的某一行。
标号是放在行首的名字,每个标号必须以一个冒号结尾。
例如:
Ifccount<0Then
GoToget_out ‘跳转到指定的标号行(get_out)
EndIf
.....
Get_out:
‘标号行(get_out)
.....
Endprogram
虽然MapBasic提供了无条件转移语句GoTo,但一般不主张在程序中太多地使用GoTo语句。
因为它使程序结构变得不容易读懂,所以除非万不得已,应尽量避免使用GoTo语句。
(2).循环语句(For...Next、Do...Loop、Do...While)
①.For...Next语句的语法如下:
Forvar_name=start_exprToend_expr[Stepinc_expr]
Statement_list
[Exit for]
②Do…Loop语句的语法如下:
语法1
语法2
Do
Statement_list
[ExitDo]
Loop[{While|Until}condition]
Do[{While|Until}condition]
Statement_list
[ExitDo]
Loop
③While...Wend循环
While condition
Statement_list
Wend
(3).提供流控制的其他语句(EndProgram)
①.结束程序(EndProgram)
EndProgram语句用于终止MapBasic应用程序,移去由应用程序创建的用户菜单项,从内存中移去应用程序。
EndProgram还能关闭所有被应用程序打开的文件,但它不能关闭任何打开的表。
②.结束程序并退出MapInfo(EndMapInfo)
EndMapInfo语句可以终止MapBasic应用程序(这一点与EndProgram相同),同时将退出MapInfo。
7.过程
一个典型的MapBasic程序由许多过程组成,每个过程都包含一组完成某一特定任务的语句。
(1).主过程与子过程
每一个MapBasic程序至少有一个过程,这个过程叫做主过程,其余的过程(称为子过程)都必须由主过程或别的子过程来调用。
DeclareSub语句声明下面将定义一个主过程或子过程。
过程的声明和定义如下:
DeclareSubMain ‘声明下面将定义主过程Main
SubMain
Note“HellofromMapBasic!
”
EndSub
(2).过程的调用
当MapInfo运行一个已编译好的应用程序时,会自动调用主过程Main。
在主过程中又可以通过Call语句调用其他子过程。
如下例:
面的程序包括两个过程:
一个主过程Main和一个子过程announce_data:
DeclareSubMain ‘声明下面将定义主过程Main
DeclareSubtody_data ‘声明下面将定义子过程tody_data
SubMain ‘主过程
Call tody_data ‘调用子过程tody_data
EndSub
Subtody_data ‘子过程tody_data
Note“Today’sdateis”+Str$(CurDate())
End Sub
(3).带参数的过程调用
如果一个子过程带有参数,那么它们要在DeclareSub语句和Sub…EndSub语句中先进行声明。
声明的方法是在过程名后面加上一对圆括号,括号里列出参数名及其类型。
如下例中调用带有日期型参数的子过程Check_date。
DeclareSubMain
DeclareSubCheck_date(last_dataAsDate)
Sub Main
Dim report_dateAsDate
Report_date=“01/01/2003”
CallCheck_date(report_date)
EndSub
SubCheck_date(last_dateAsDate)
Dim elapsed_daysAsSmallInt
Elapsed_days=CurDate()–last_date
Ifelapsed_days=l80 Then
Last_date=CurDate()
EndIf
EndSub
上例中的子过程是检查日期型的参数的值是否太旧(距当前日期超过180天,如果这个日期型参数的值太旧,则把这个参数设置为当前日期值。
(4).形式参数传递
MapBasic过程参数是以形式参数的方法传递的,使用形式参数应遵循以下规则:
·在Call语句中必须指定一个变量名作为形式参数。
·如果被调用的子过程赋了一个新的值给形式参数,那么这个新的值将自动存到调用者的变量中。
换句话说,子过程可以通过形式参数把值返回给调用者。
因此,上面的例子中,Call语句中指定的一个变量名report_date:
CallCheck_date(report_date)
在过程Check_date中有一个名叫last_date的参数,当过程Check_date执行赋值语句last_date=CurDate()时,MapBasic自动更新主过程中变量report_date的值。
8.函数
MapBasic支持多种不同的函数。
有标准BASIC函数(例如Asc()、Format()、Val()等,以及MapInfo或MapBasic特有的函数(例如Distance()、ObjectGeography()等)。
除此以外,MapBasic还可以自定义用户函数,一旦定义了一个用户函数,就可以像MapBasic标准函数一样调用它。
定义用户函数语句的语法如下:
Function name([[ByVal]parameterAsdatatype][,[ByVal]parameterAsdatatype...])Asreturn_type
statement_list
EndFunction
下面的例子定义了一个用户函数money_format,它把一个数值参数转变成一个字符串(通过Format$()函数),对应于用逗号(,)分隔的美元计数格式:
DeclareSubMain
DeclareFunctionmoney_format(ByValnumAsFloat)Asstring
SubMain
Dim dollar_amountAsString
Dollar_amount=money_format(123456789)
EndSub
Functionmoney_format(ByValnumAsFloat)Asstring
money_format=Format$(num,”$,#.##($,#.##”)
EndFunction
应用程序中可以定义与标准MapBasic函数同名的用户函数。
当程序调用这个名字的函数时,真正被调用的是用户函数而不是标准函数。
二.创建MapBasic应用程序
1.创建MapBasic应用程序的基本过程
(1)运行MapBasic打开开发环境,如图5-01。
在主菜单中选择File->New,打开新的程序编辑窗口。
图5-01 MapBasic开发环境
(2)在编辑窗口中输入一行MapBasic程序代码,如图5-02所示。
图5-02MapBasic
(3)在主菜单中选择File->Save,将该程序保存为一个MapBasic源代码文件,例如first.mb。
(4)选择Project->CombileCurrentFile,对程序进行编译。
如果编译成功将自动生成一个相应的可执行文件,在本例中为first.mbx;
(5)启动MapInfo。
选择MapInfo中Tools->RunMapBasicProgram…,选择编译生成的可执行文件first.mbx,MapInfo将运行该程序,程序运行结果如图5-03所示。
(6)或者,在MapBasic中,选择Project->Run系统将自动启动MapInfo系统,并执行刚才生成的可执行文件first.mbx。
在这个简单的实例中,演示了MapBasic程序开发基本过程——从程序创建、代码输入、编译和运行的全过程。
在实际的程序开发中每一步都比实例复杂,下面分步介绍各阶段中常见问题及处理方法。
2.建立一个项目文件的步骤:
①.选择[File]>[New]打开一个编辑窗口。
②.在编辑窗口中输入下面这一行:
[Link]
③.接着输入这样一行文本Application=appfilename(这里appfilenams是指建立的可执行文件的文件名)。
例如:
Application=C:
\MB\CODE\CUSTOM.MBX
④.接着再输入一行文本Module=modulename(这里mdulename是指MapBasic的目标文件名),例如:
Module=C:
\MB\CODE\CUSTOM.MBO
请注意文件的扩展名,MapBasic的目标文件的扩展名为.mbo。
当多模块项目中的一个单独的模块被编译时,MapBasic就会为它建立一个目标文件。
当选择[project]>[CompileCurrentFile]时,MapBasic就会试图把当前文件编译成一个可执行文件(扩展名为.mbx)。
如果该程序文件调用了不在此文件中的函数或过程,MapBasic则不能建立一个.mbx文件。
在这种情况下MapBasic假设它只是一个大项目的一个部分,而把它编译成一个目标文件(.mbo)。
另外,当一个程序没有主过程时,MapBasic在编译时也把它编译成一个目标文件。
⑤重复第④步,直到包括应用程序的所有模块。
⑥选择[File]>[SaveAs]保存项目文件。
注意在SaveAs对话框中选择文件类型中的“ProjectFile”(从对话框左下角的文件类型列表中选择),以便使保存的项目文件有扩展名.mbp。
最后选择“file->save”命令保存这个工程文件,扩展名为.mbp。
现在按照下面的方法来编辑和链接这个工程文件:
(1)编译每个在工程文件中使用的模块,选择Project菜单中的“compilecurrentfile”命令。
(2)选择Project菜单中的“selectprojectfile”命令,在打开的对话框中,选择一个工程文件,以让MapBasic知道哪个工程文件需要链接。
(3)选择Project菜单中的“linkcurrentproject”命令以完成对应用程序的链接。
MapBasic读列在工程文件中的对象文件(.mbo)。
若链接无错误,则MapBasic建立一个可执行文件(.mbx);若有错误,则显示错误信息。
3.调试程序
调试程序一般是指发现并改正运行错误的过程。
有些运行错误很容易纠正,例如由输入错误引起的(原应输入表名“states”而不是“stats”)。
但是另外一些错误却很难定位,为了帮助检测和纠正程序中的错误,MapBasic提供了调试程序的工具(Stop和Continue语句)。