数组与数组对应位置两个数值任意将一个数组的值赋值给另一个数组值一样,8个数值符合要求的将组名提取到指定单元格

VFP是关系型数据库管理系统,能管理和操作数据库;同时也是一种高级程序设计语言,具有一般计算机语言的特点。要开发高质量的数据库应用系统,必须掌握VFP语言。本章主要介绍VFP中使用的数据类型、运算符、表达式、函数及数据存储方式等内容。2.1 数据类型数据类型决定了数据的存储方式和运算方式,要管理和操作数据,首先需要定义其类型。在VFP中,数据类型有以下13种。1. 字符型(Character) 是用各种文字字符表示的数据,由字母、数字、汉字、符号和空格等组成。长度为0~254字节,每个半角字符占1字节。字符型数据可用来保存姓名、地址和不需要进行算术运算的数字(如电话号码、邮编)等。2. 数值型(Numeric) 是可以进行算术运算的数据,由数字0~9、小数点、正或负号构成,最多1~20位。宽度包含小数点和小数位数。在内存中,占用8字节,取值范围在-0.9999999999×1019~0.9999999999×1020之间,存储时需要转换成ASCII码。3. 货币型(Currency) 表示货币量时用货币型来代替数值型数据,占用8字节,取值范围在-922337203685477.5808~922337203685477.5807之间,小数位超过4位时将自动四舍五入到四位。4. 逻辑型(Logic) 是用来进行各种逻辑判断的数据,只有两个值:真或假,长度固定为1字节。实际存储时只存放T或F两个字母中的一个。5. 日期型(Date) 是用来表示日期的数据,存储格式为“YYYYMMDD”,其中YYYY代表年,MM代表月,DD代表日,长度固定为8字节。日期型数据的表示有多种格式,VFP默认的是美国日期格式“MM/DD/YY”,如1996年3月20日表示为“03/20/96”。可以通过SET DATE,SET CENTURY命令或通过“工具|选项”菜单,打开“选项”对话框,设置其他日期格式。日期型数据的取值范围是:公元0001年1月1日~公元9999年12月31日。6. 日期时间型(DateTime) 是用来描述日期和时间的数据,存储格式为“YYYYMMDDHHMMSS”,其中YYYY代表年,前两个MM代表月,DD代表日,HH代表小时,后两个MM代表分钟,SS代表秒,长度固定为8字节。日期时间型数据的日期部分也具有多种显示格式,并可以通过SET DATE,SET CENTURY命令进行设置;时间部分的显示格式可以通过SET HOURS,SET SECONDS等命令进行设置。取值00:00:00A.M.~11:59:59P.M.。以下数据类型只能用于数据表中的字段。7. 整型(Integer) 是指不包含小数点部分的数值,以二进制形式存储,长度固定为4字节,取值范围在-2147483647~2147483646之间。8. 浮点型(Float) 是数值型数据的一种,与数值型数据完全等价,但在存储形式上采取浮点格式,由尾数、阶数及字母E组成,占用8字节。采用浮点型数据的主要目的是使计算具有较高的精度。9. 双精度(Double) 是具有更高精度的数值型数据,占用8字节,取值范围在±4.94065645841247E-324~±1.797693413486232E+308之间。10. 备注型(Memo) 存储字符型数据块,长度固定为4字节,用来存储指向实际数据存放位置的地址指针,实际数据存放在与数据表文件同名的.FPT文件中,其长度仅受磁盘空间的限制。11. 通用型(General) 存储OLE对象,该字段包含了对OLE对象的引用,OLE对象的实际内容由其他应用程序建立,可以是文档、图片、电子表格等对象。通用型数据固定长度固定为4字节,用来存储指向.FPT文件位置的地址指针。12. 字符型(二进制)数据 用于存储任意不经过代码页修改而维护的字符型数据,长度为1~254字节。13. 备注型(二进制)数据 用于存储任意不经过代码页修改而维护的备注型数据,长度固定为4字节。数据类型是数据的基本属性,对数据进行操作时,数据必须是同类型的;若同时对不同类型的数据进行操作,系统将判语法出错。2.2 数据存储在VFP中,将用于存储数据的常量、变量、数组、字段、记录和对象称为数据的存储容器,它们决定了数据的类型和存储方法。2.2.1 常量常量是指在数据处理过程中其值保持不变的量。VFP支持6种类型的常量,即数值型、字符型、逻辑型、日期型、日期时间型和货币型。1. 数值型数值型常量是数学中的十进制整数或小数,例如10.25,-123.567(记为N型)。要表示很大或很小的数值型常量,可采用科学计数法,例如,1.234×1015用1.234E+15表示,1.234×10-15用1.234E-15表示(数值型常量的浮点格式,也称浮点型常量,记为F型)。2. 字符型字符型常量是用定界符括起来的字符串。定界符有三种,即西文单引号、双引号和方括号,字符串由汉字和ASCII码中可打印的字符组成,如'abc',"123",[VFP数据库]。若无定界符,系统会把该字符串当成变量名。注意:字符型常量的定界符必须成对出现,不能一边用单引号而另一边用双引号。当字符串本身包含一种定界符时,必须使用另一种定界符来表示该字符串常量,如"古语云:'一份耕耘一份收获'"。3. 逻辑型逻辑型常量用下圆点定界符括起来,只有真和假两个值。用.T., .t., .Y., .y.表示逻辑真;用.F., .f., .N., .n.表示逻辑假。圆点和字母都必须是半角符号,相互之间不能有空格。4. 日期型日期型常量用来表示一个确切的日期,用花括号作为定界符,默认为美国日期格式(MM/DD/YY)。日期型常量通常通过转换函数CTOD(<字符表达式>)把日期格式的字符串转换成日期型数据,例如,2007年3月20日可用CTOD("03/20/07")表示为日期型常量。通过SET DATE,SET CENTURY等命令可以改变默认的日期格式。(1)SET DATE命令格式:SET DATE TO AMERICAN|ANSI|BRITISH|FRENCH|GERMAN|ITALIAN|JAPAN|USA|MDY|DMY|YMD功能:设置当前日期的格式,设置结果如表2-1所示。表2.1 常用日期格式及其设置说明:命令行中的竖杠分隔内容表示选择其中的一项。(2)SET CENTURY命令格式:SET CENTURY ON|OFF功能:设置年份的位数,ON指定年份为4位,OFF指定年份为2位。【例2.1】 用不同的日期格式显示系统的当前日期。在命令窗口中输入以下命令(从 &&开始的内容为注释部分,可以不输入),并分别按回车键执行。注意:后面的例子中用到的命令都是在命令窗口中输入,按回车键执行的。
?DATE() && 调用日期函数
SET DATE TO YMD
&& 设置年月日格式
?DATE()
SET CENTURY ON
&& 设置年份为4位数字
?DATE()
显示结果为:
05/20/10
&& 按默认的美国日期格式显示
10/05/20
&& 按年月日格式显示
2010/06/20
&& 年份用4位数字显示
在VFP中,还有一种严格的日期格式,其格式为{^YYYY-MM-DD}。(^)符号表明该格式是严格的日期格式,并按照YMD的格式解释。严格的日期格式可以在任何情况下使用,不受SET DATE,SET CENTURY等语句设置的影响。例如,2006年3月20日用严格的日期格式可表示为{^2006-03-20}。5. 日期时间型日期时间型常量包括日期和时间两部分内容,例如,2006年03月20日11时35分15秒可表示为{^2006-03-20 12:30:15}。6. 货币型货币型常量用符号“$”来标识,如$567.8。2.2.2 变量变量是指在数据处理过程中其值可以改变的量,包括字段变量和内存变量两种。内存变量又分为一般内存变量、系统内存变量和数组变量。1. 变量的命名每个变量都有一个名称,叫做变量名。变量名的命名规则是:(1)由汉字、字母、数字和下划线组成,而且必须以汉字、字母或下划线开头。(2)长度为1~128个字符,国标基本集上的一个汉字占2个字符位,扩充集上的一个汉字占4个字符位。(3)不能使用VFP的保留字。2. 字段变量字段变量存在于数据表文件中,每个数据表中都包含若干个字段变量,其值随着数据表中记录的变化而改变。要使用字段变量,须先打开包含该字段的表文件。在数据表中,对字段变量必须先定义后赋值,然后才可以使用。对字段变量的定义是在定义数据表结构时完成的,主要给出变量名、变量类型、变量宽度及数值型数据的小数位数等。有关字段变量的定义和使用将在第3章介绍。3. 内存变量内存变量独立于数据表文件,存在于内存之中,是一种临时的工作单元,需要时可以临时定义,不需要时可以随时释放,常用来存储常数、程序运行的中间结果及最终结果。内存变量的类型取决于赋予的变量值类型,可以把不同类型的数据赋给同一个变量。内存变量的数据类型有:字符型(C)、数值型(N)、货币型(Y)、逻辑型(L)、日期型(D)和日期时间型(T)。当内存变量名与数据表中的字段变量名相同时,如要先访问该内存变量,必须在变量名前加上前缀M.或M->(由减号加大于号组成),否则,系统将优先访问同名的字段变量。(1)建立内存变量在VFP中,给变量命名,应力求“见名知义”。简单内存变量不必事先定义,可以直接通过赋值语句建立。变量的赋值命令有以下两种格式。格式1:<内存变量名> = <表达式> && 等号“=”是赋值语句格式2:STORE <表达式> TO <内存变量名>功能:在定义内存变量名的同时确定内存变量的值和类型。说明:① 定义内存变量名、赋值和确定变量的类型在同一个命令中完成。② 语句中的<表达式>可以是一个具体的值,也可以是一个表达式。如果是表达式,系统将先计算表达式的值,再将此值赋给变量。③ 格式1一次只能给一个内存变量赋值,而格式2可以同时给多个变量赋相同的值,但是要求各变量之间必须用西文逗号隔开。④ 可以通过给内存变量重新赋值来改变其值和类型。【例2.2】 定义变量。
X=5
&& 定义变量X,并把数值5赋给X
STORE X+10 TO Y
&& 定义变量Y,并将表达式X+10的值赋给Y
STORE"北京"TO A,B,C
&& 定义变量A,B,C,并赋给相同的字符数据
X=.F.
&& 重新定义变量X,并赋给逻辑值.F.
(2)输出内存变量的值格式1:? <表达式表>格式2:?? <表达式表>功能:计算<表达式表>中各表达式的值并在屏幕上显示出来。说明:格式1在输出前先执行一次回车换行,再输出各表达式的值;格式2直接在当前光标所在位置处输出表达式的值。【例2.3】 输出内存变量的值,接例2.2的命令操作,继续在命令窗口中输入以下命令,按回车键执行。
?X
?? A,B,C
?Y
显示结果:
.F.北京 北京 北京
15
(3)显示或打印内存变量格式:LIST|DISPLAY MEMORY [LIKE <通配符>][TO PRINTER|TO FILE <文件名>]功能:显示或打印内存变量的当前信息。说明:① 命令行中方括号中的内容是可选的,尖括号中的内容由用户提供。② TO PRINTER表示将显示的结果送打印机输出。③ TO FILE <文件名> 表示将显示结果保存到一个扩展名为.TXT的文本文件中。④ LIKE <通配符>表示显示或打印所有与通配符一致的内存变量,通配符包括“?”和“*”。“?”表示任意一个字符,“*”表示任意多个字符。⑤ LIST和DISPLAY用法相同,区别仅在于LIST连续显示,DISPLAY分页显示。⑥ 无任何选项时,将显示当前内存中的下列信息:已定义的内存变量或数组变量、已定义的菜单系统、下拉菜单和窗口等用户定义信息,以及系统内存变量信息。⑦ 显示信息的第1列为内存变量的名字,第2列为变量的作用域,第3列为变量的类型,第4列为变量的值,第5列为数值型内存变量的计算机内部表示。【例2.4】 显示内存变量。
M1="123"
&& 表示把字符串123赋值给M1
M2=5
&& 表示把数值的5赋值给M2
M3=.F.
&& 表示把逻辑值.F.赋值给M3
LIST MEMORY LIKE M*
&& 显示所有第1个字符为M的内存变量信息
显示结果:
M1
Priv
C
"123"
&& 表示123是字符串,不是数值
M2
Priv
N
5
(
5.00000000)
M3
Priv
L
.F.
(4)释放内存变量释放内存变量就是将内存中的内存变量删除,腾出在内存中所占用的空间。格式1:CLEAR MEMORY && 释放所有内存变量格式2:RELEASE <内存变量名表>格式3:RELEASE ALL [LIKE <通配符>|EXCEPT <通配符>]功能:释放所有内存变量或指定的内存变量。说明:① 命令只清除用户自定义的内存变量,而不清除系统内存变量。② 带LIKE <通配符>的选项表示清除与通配符相匹配的内存变量,带EXCEPT<通配符>的选项表示清除与通配符不相匹配的内存变量。【例2.5】 清除内存变量的几种情况举例。
RELEASE M1
&& 释放内存变量M1
RELEASE ALL LIKE M*
&& 释放所有第1个字母为M的内存变量
RELEASE ALL
&& 释放所有内存变量,该命令与CLEAR MEMORY的效果相同
4. 系统内存变量系统内存变量是指VFP系统定义的一些变量,通常以下划线“_”开头,如_PAGENO,_ALIGNMENT等。5. 数组数组是内存中连续的一片存储区域,由一组变量组成。每个数组元素通过数组名及相应的下标被引用,相当于一个一般内存变量。通过赋值语句可以为各个元素分别赋值,且所赋值的数据类型可以不同。(1)数组的定义格式:DIMENSION <数组名1> (<数值表达式1> [,<数值表达式2>])[,<数组名2>(<数值表达式3> [,<数值表达式4>])]…功能:定义一个或若干个一维或二维数组。说明:① DIMENSION命令与DECLEAR命令等价,且可以同时定义多个数组。② <数值表达式>为数组下标,当只选择<数组名1>和<数值表达式1>时,定义的是一维数组,如DIMENSION aa(5),数组aa中包含5个元素:aa(1),aa(2),aa(3),aa(4)和aa(5);当选择<数组名1>、<数值表达式1>和<数值表达式2>时,定义的是二维数组,如DIMENSION bb(2,4),数组bb中包含8个元素:bb(1,1),bb(1,2),bb(1,3),bb(1,4),bb(2,1),bb(2,2),bb(2,3)和bb(2,4)。注意:数组下标的引用从1开始。③ 数组的下标可以用圆括号或方括号括起来, 如DIMENSION aa(5)与DIMENSION aa[5]等价。④ 数组定义后,系统自动给每个元素赋以逻辑假值.F.。可以用有关命令给每个数组元素重新赋值。⑤ 在同一运行环境下,数组名不能与单个内存变量重名。【例2.6】 定义一个一维数组AA和一个二维数组BB举例。
DIMENSI0N
AA(5),BB(2,3)
&& 定义一个一维数组AA和一个二维数组BB
STORE
0
TO
AA
&& 将数值0赋给数组AA中的所有元素
BB(1,1)="XYZ"
&& 将字符串XYZ赋给数组元素BB(1,1)
BB(2,1)=125
&& 将数值125赋给数组元素BB(2,1)
BB(2,3)=.T.
&& 将逻辑真值T赋给数组元素BB(2,3)
DISPLAY
MEMORY
&& 查看数组变量
2.2.3 其他数据存储容器1. 字段、记录和数据表数据表是一系列相关数据的集合。字段是数据表中存储、处理数据的基本元素,一个具体的字段只能存储一种类型的数据。记录是数据表中一组字段的集合,同一个数据表中的所有记录都具有相同的字段名,且同名字段在每个记录中的数据类型、数据长度都是相同的。字段和记录构成了一个数据表的全部内容,在VFP中就是以记录为单位组织数据的。2. 对象对象(Object)是一个具有属性和行为特征的实体,在面向对象程序设计中,对象是编程的基本元素,它将某一数据和使用该数据的一组基本操作或过程封装在一起,构成一个统一体。每个对象都有自己的属性和行为特征。VFP的对象可以是表单、表单集或各种控件。有关对象的概念和使用将在第7章中具体介绍。2.3 运算符和表达式运算符是对相同类型的数据进行运算操作的符号。用运算符将常量、变量和函数等数据联接起来的式子称为表达式。表达式的类型由运算符的类型决定,每个表达式按照规定的运算规则产生一个唯一的值。2.3.1 数值运算符及数值表达式数值表达式是由算术运算符将数值型常量、变量和函数等联接起来的式子,其结果仍是数值型数据。VFP提供的算术运算符如表2-2所示,它们的作用与数学中的算术运算符相同,运算优先级依次为:括号→乘方→乘、除、取模→加、减,其中乘、除和取模同级,加和减同级。同级时,分别从左到右进行计算。表2.2 算术运算符【例2.7】 计算数值表达式的值。
?2*10/5,128%5
&&(注意表达式间用半角逗号隔开)结果为
4
3
x=2
&& 把数值2赋值给x
y=3
&& 把数值3赋值给y
z=4
&& 把数值4赋值给z
?(x*y-4)/2
&& 结果为
1.0000
2.3.2 字符串运算符及字符表达式字符表达式是由字符串运算符将字符型常量、变量和函数等联接起来的式子,其结果仍然是字符型数据。字符串运算符有以下两种,它们的优先级相同。(1)+ 两个字符串首尾相连形成一个新的字符串。(2)- 两个字符串相连,并将前字符串尾部的空格移到合并后的新字符串的尾部。【例2.8】 字符串运算。
?"ABCD
"+"EFG"+"1234"
&& 结果为
ABCD
EFG1234
?"ABCD
"-"EFG"+"1234"
&& 结果为
ABCDEFG
1234
2.3.3 日期运算符及日期表达式日期表达式是由日期运算符将日期型常量、变量、函数等联接起来的式子,其结果为日期型数据或者数值型数据。日期型运算符只有加法(+)和减法(-)两种。<日期型数据> + <数值型数据>:结果为日期型数据(指定日期若干天后的日期)<日期型数据> - <数值型数据>:结果为日期型数据(指定日期若干天前的日期)<日期型数据> - <日期型数据>;结果为数值型数据(两个日期相差的天数)【例2.9】 日期运算。
Set date to YMD
&& 设置日期格式为年月日的形式
?{^2007-01-20}+5
&& 结果为日期
2007/01/25
?{^2007-01-20}-5
&& 结果为日期
2007/01/15
?{^2007-01-20}-{^2006-10-28}
&& 结果为天数
84
2.3.4 关系运算符及关系表达式关系表达式是由关系运算符、数值表达式、字符表达式或者日期型表达式组合而成的式子,其结果为逻辑真值(.T.)或逻辑假值(.F.)。关系运算符及其含义如表2-3所示。表2.3 关系运算符说明:(1)关系运算符的优先级相同,从左到右依次进行比较。(2)关系运算符的两边可以是字符表达式、数值表达式或者日期表达式,但两边的数据类型必须一致。(3)数值型数据按数值的大小比较,日期型数据依次按年月日的值比较。字符型数据按照其机内码顺序比较,对于西文字符,是ASCII码的值;对于汉字,是汉字国标码的值。常用的一级汉字按照拼音顺序排列。两个字符串比较时,自左至右逐个字符进行比较。(4)字符串包含运算符“$”用来检测左边的字符串是否包含在右边的字符串中,若包含(即前者是后者的一个子字符串),结果为逻辑真;否则,结果为逻辑假。(5)字符串精确比较运算符“==”用于精确匹配,即只有当两个字符串完全相同时,结果才为逻辑真;否则,结果为逻辑假。在用等号比较运算符“=”比较两个字符串时,运算结果与系统的设置状态SET EXACT ON|OFF有关。当处于OFF状态时(这是系统的默认状态),进行的是不精确匹配,只要“=”右边的字符串是左边字符串的前缀,结果就为真。当处于ON状态时,进行的是精确匹配,只有“=”两边的字符串完全相同,结果才为真。无论EXACT为ON还是OFF,字符串精确比较运算符“==”进行的都是精确匹配。EXACT的状态设置可以用命令方式完成,也可以选择“工具|选项”命令,打开“选项”对话框,在“数据”选项卡中设置。【例2.10】 计算关系表达式的值。
① ?{^2002-01-20}>{^2001-12-30},"Fox"$"FoxPro",5+5<6
S1="读者"
&& 把字符串常量“读者”赋值给S1
S2="读者文摘"
&& 把字符串常量“读者文摘”赋值给S2
SET EXACT ON
② ?S1=S2,S2=S1,S2==S1
SET EXACT OFF
③ ?S1=S2,S2=S1,S2==S1
显示结果:
① .T..T..F.
② .F..F..F.
③ .F..T..F.
2.3.5 逻辑运算符及逻辑表达式逻辑表达式是由逻辑运算符将逻辑型常量、逻辑型内存变量、逻辑型数组、返回逻辑型数据的函数和关系表达式联接起来的式子,其结果仍然为逻辑值。逻辑运算符及其含义如表2-4所示,逻辑运算规则如表2-5所示。表2.4 逻辑运算符(说明:逻辑运算符.AND.,.OR.和.NOT.可以省略两边的点,写成AND,OR和NOT。)表2.5 逻辑运算规则逻辑运算符的优先次序为:NOT,AND,OR,可以用括号来改变逻辑运算的先后次序。在同一表达式中,如使用了不同类型的运算符,则各种运算符的优先顺序由高到低为:括号→算术运算符→字符串运算符→关系运算符→逻辑运算符。【例2.11】 逻辑运算举例。
?10>5.AND.5<2,10>5.OR.5<2
&& 结果为 .F.,.T.
x1=3
&& 把数值3赋值给x1
y1=-2
&& 把数值-2赋值给y1
x2=8
&& 把数值8赋值给x2
y2=-6
&& 把数值-6赋值给y2
?x1+y1>x2+y2.AND..NOT.(y1<y2)
&& 结果为 .F.
最后一个表达式的运算顺序为2.3.6 类与对象运算符类与对象运算符专门用于面向对象程序设计,它有两种形式。(1)点运算符(.)主要用于确定对象与类的关系,以及属性、事件和方法与其对象的从属关系。例如,设计表单时,要将表单的Caption(标题)属性设置为“输入记录”,在程序中用命令表示为:Thisform.caption="输入记录"。(2)作用域运算符(::)用于在子类中调用父类。例如,MyCommandButton::Click表示MyCommandButton对象继承其父类的Click事件过程。2.3.7 名称表达式名称表达式是指能代替字符型变量或数组元素的值的一个引用。名称不是变量,也不是数组元素,但它可以替代字符变量或数组元素中的值。名称表达式为VFP的命令和函数提供了灵活性,将名称存放到内存变量或数组元素中,并用小括号括起该变量,就可以在命令或函数中用变量来代替该名称了。定义一个名称时,只能以字母、汉字或下划线开头,且名称中只能使用字母、汉字、数字和下划线字符,不能使用VFP的保留字,名称的长度为1~128个字符。一次可定义多个名称,名称之间用逗号分开。在VFP中,可以使用的名称有:表(.DBF)文件名、表别名、表字段名、索引文件名、内存变量名和数组名、窗口名、菜单名、表单名、对象名、属性名等。【例2.12】 使用名称表达式打开一个名为“学生.DBF”的数据表文件。
STORE "E:\VFP6\DATA\学生.DBF" TO CC
USE(CC)
&&USE命令用于打开一个表文件(假设学生表已经建立)
2.4 函数函数(Function)是按照给定的参数返回一个值的表达式,与命令一样,是系统内部“编制”好的一段程序,能够完成某种特定操作或功能。其一般格式是:函数名([参数1][,参数2][,…])&&命令中的括号、逗号、圆点、引号等均取西文一个函数必须有一个函数名,其后必须跟一对圆括号,括号内可以有0~n个参数(自变量),函数的运算结果有唯一的值,称为返回值。说明:① 对于某些没有参数的函数,圆括号内为空,如系统日期函数DATE( )。② 当函数带有多个参数时,参数和参数之间用逗号分隔。③ 任何可以使用表达式的地方都可以使用函数,表达式将函数的返回值作为运算对象。例如,命令“?DATE( )+100”显示从系统当前日期算起100天后的日期。使用函数可以大大丰富命令的功能。在VFP中,函数有两种:一种是系统函数,另一种是用户自定义函数。系统函数是由VFP提供的内部函数,大约有380多个,可以随时调用;自定义函数是由用户根据需要自行编写的。本节主要介绍常用的系统函数,用户自定义函数将在6.4.2节中介绍。注意:本节例题中使用的命令都在VFP的命令窗口中输入,按回车键执行。2.4.1 数值处理函数(1)取整函数格式:INT(<数值表达式>)功能:返回数值表达式的整数部分。【例2.13】
?INT(4.98)
&& 结果为
4
?INT(-5.68)
&& 结果为
-5
?INT(10.5+7.4)
&& 结果为
17
(2)四舍五入函数格式:ROUND(<数值表达式1>,<数值表达式2>)其中<数值表达式2>指定保留的小数位数。功能:对<数值表达式1>在由<数值表达式2>指定小数位数后的值进行四舍五入运算。说明:①<数值表达式2>大于或等于0时,<数值表达式1>保留指定的小数位数。②<数值表达式2>小于0时,其绝对值表示整数部分四舍五入的位数。【例2.14】
?ROUND(35.865,2)
&& 结果为
35.87
?ROUND(35.865,0)
&& 结果为
36
?ROUND(35.865,-1)
&& 结果为
40
?ROUND(135.865,-2)
&& 结果为
100
(3)取绝对值函数格式:ABS(<数值表达式>)功能:求数值表达式的绝对值。【例2.15】
?ABS(25)
&& 结果为
25
?ABS(-25)
&& 结果为
25
(4)求最大值函数格式:MAX(<数值表达式1>,<数值表达式2> [,<数值表达式3>…])功能:返回几个数值表达式中最大的值。【例2.16】
?MAX(-30,-20)
&& 结果为
-20
?MAX(-30,-40,20)
&& 结果为
20
(5)求最小值函数格式:MIN(<数值表达式1>,<数值表达式2> [,<数值表达式3>…])功能:返回几个数值表达式中最小的值。【例2.17】
?MIN(-30,-20)
&& 结果为
-30
?MIN(-30,-40,20)
&& 结果为
-40
(6)求平方根函数格式:SQRT(<数值表达式>)功能:返回数值表达式的算术平方根值。【例2.18】
?SQRT(25.46)
&& 结果为
5.05
(7)求自然对数函数格式:LOG(<数值表达式>)功能:求数值表达式的自然对数值。【例2.19】
?LOG(32.78)
&& 结果为
3.49
(8)幂函数格式:EXP(<数值表达式>)功能:求数值表达式对于e的幂的值。【例2.20】
?EXP(4.43)
&& 结果为
83.93
(9)求余数函数格式:MOD(<数值表达式1>,<数值表达式2>)功能:求<数值表达式1>除以<数值表达式2>的余数,且<数值表达式2>的值不能为0。说明:函数返回值的符号与<数值表达式2>的符号相同。如果<数值表达式1>与<数值表达式2>同号,函数值即为两数相除的余数;如果<数值表达式1>与<数值表达式2>异号,则函数值为两数相除的余数再加上<数值表达式2>的值。【例2.21】
?MOD(15,4),MOD(15, -4),MOD(-15,4),MOD(-15, -4)
显示结果: 3-1 1-32.4.2 字符处理函数(1)宏替换函数格式:&<字符型变量> [.]功能:替换一个字符型变量的内容,即&的值是变量中的字符串。如该函数与其后的字符无明确分界,则要用西文的圆点“.”作为函数结束标识。宏替换可以嵌套使用。说明:宏替换可以在任何能接受字符串的命令或函数中使用。【例2.22】
AA="BB"
BB="清华大学"
?AA,BB,&AA
&& 结果为
BB清华大学 清华大学
? "&BB.是一所著名的大学"
&& 结果为
清华大学是一所著名的大学
X="25.5"
?32.5+&X
&& 结果为
58.00
(2)求字符串长度函数格式:LEN(<字符表达式>)功能:计算字符串中的字符个数,返回结果为数值型。【例2.23】
?LEN("ABCDE")
&& 结果为
5
X="清华大学"
?LEN(X)
&& 基本集一个汉字占有2个字符长度,结果为
8
(3)生成空格函数格式:SPACE(<数值表达式>)功能:产生由数值表达式指定数目的空格,返回结果为字符型。【例2.24】
?"清华"+SPACE(4)+"大学"
&& 结果为
清华
大学(清华与大学间有4个空格)
(4)字符串转换成小写字母函数格式:LOWER(<字符表达式>)功能:将字符表达式中的大写字母转换成小写字母。【例2.25】
?LOWER("Visual FoxPro")
&& 结果为
visual foxpro
(5)字符串转换成大写字母函数格式:UPPER(<字符表达式>)功能:将字符表达式中的小写字母转换成大写字母。【例2.26】
?UPPER("Visual FoxPro")
&& 结果为
VISUAL FOXPRO
(6)删除字符串尾部的空格函数格式:TRIM(<字符表达式>)功能:将字符串尾部的空格删除。【例2.27】
X="清华大学"
?LEN(X)
&& 结果为
10
Y=TRIM(X)
?LEN(Y)
&& 结果为
8
(7)删除字符串左边空格函数格式:LTRIM(<字符表达式>)功能:将字符串的前导空格删除。【例2.28】
X="清华大学"
?LEN(X)
&& 结果为
10
Y=LTRIM(X)
?LEN(Y)
&& 结果为
8
(8)删除字符串右边空格函数格式:RTRIM(<字符表达式>)功能:与TRIM( )函数功能相同,删除字符串尾部空格。(9)删除字符串最左边和最右边的所有空格函数格式:ALLTRIM(<字符表达式>)功能:删除字符串中最左边和最右边的所有空格。【例2.29】
X="Visual FoxPro"
?LEN(X)
&& 结果为
20
?LEN(ALLTRIM(X))
&& 结果为
13
(10)取子字符串函数格式:SUBSTR(<字符表达式>,<数值表达式1> [,<数值表达式2>])功能:从指定的<字符表达式>中,截取一个子字符串。子字符串的起点位置由<数值表达式1>给出,截取子字符串的字符个数由<数值表达式2>给出。说明:如省略<数值表达式2>,截取的字符串将从<数值表达式1>给出的位置一直到该字符表达式的结尾。【例2.30】
A="清华大学"
?SUBSTR(A,1,4)
&& 结果为
清华
?SUBSTR(A,5)
&& 结果为
大学
(11)取左边子字符串函数格式:LEFT(<字符表达式>,<数值表达式>)功能:从指定的<字符表达式>左边开始截取<数值表达式>指定个数的字符。说明:如<数值表达式>给出的值大于字符表达式中字符的个数,则返回整个<字符表达式>;如<数值型表达式>的值为0或负数,则返回结果为空串。【例2.31】
?LEFT("清华大学",4)
&& 结果为
清华
(12)取右边子字符串函数格式:RIGHT(<字符表达式>,<数值表达式>)功能:从指定的<字符表达式>右边截取<数值表达式>指定个数的字符。说明:如<数值表达式>给出的值大于<字符表达式>中字符的个数,则返回整个字符表达式。如<数值表达式>的值为0或负数,则返回结果为空串。【例2.32】
?RIGHT("清华大学",4)
&& 结果为
大学
(13)子字符串位置测试函数格式:AT(<子字符串>,<主字符串> [,<数字>])功能:求<子字符串>在<主字符串>中的起始位置,函数返回值为数值型。说明:<数字>表示<子字符串>在<主字符串>中第几次出现,默认为第1次。如<子字符串>不在<主字符串>中,返回值为零。【例2.33】
?AT("大学","清华大学是一所著名大学")
&& 结果为
5
?AT("大学","清华大学是一所著名大学",2)
&& 结果为
19
2.4.3 日期和时间处理函数(1)系统当前日期函数格式:DATE( )功能:返回当前系统日期值,函数值为日期型,其格式由SET DATE, SET CENTURY等设置状态决定。【例2.34】
?DATE()
&& 结果为
06/20/10(机器上的当前日期)
SET CENTURY ON
&& 设置显示日期表达式中的世纪部分
?DATE()
&& 结果为
06/20/2010
(2)系统当前时间函数格式:TIME([<数值表达式>])功能:以24小时制的时、分、秒(HH:MM:SS)格式显示系统的当前时间,函数值为字符型。说明:如函数的参数中包含<数值表达式>,则返回的时间值包含百分之几秒,数值表达式可以是任意值。【例2.35】
?TIME()
&& 结果为
18:20:32(机器上的当前时间)
?TIME(2)
&& 结果为
18:20:32.15
(3)系统日期和时间函数格式:DATETIME( )功能:返回当前系统的日期时间,函数值为日期时间型。【例2.36】
?DATETIME()
&& 结果为
05/20/10 06:23:20 PM
(4)日子函数格式:DAY(<日期型表达式>|<日期时间型表达式>)功能:返回日期型或日期时间型表达式中的日子值,函数返回值为数值型。【例2.37】
?DAY(DATE())
&& 结果为
20(假设系统当前日期为2010年5月20日)
(5)月份函数格式:MONTH(<日期型表达式>|<日期时间型表达式>)功能:返回日期型、日期时间型表达式的月份值,函数返回值为数值型。【例2.38】
?MONTH(DATE())
&& 结果为
4(假设系统当前日期为2010年5月20日)
(6)年份函数格式:YEAR(<日期型表达式>|<日期时间型表达式>)功能:返回日期型、日期时间型表达式的年份值,函数返回值为数值型。【例2.39】
?YEAR(DATE())
&& 结果为
2010(假设系统当前日期为2010年5月20日)
2.4.4 数据类型转换函数(l)字符转换成ASCII码函数格式:ASC(<字符表达式>)功能:把<字符表达式>中的第一个字符转换成相应的ASCII码数值,函数返回值为数值型。【例2.40】
?ASC("Visual FoxPro")
&& 结果为
86
(2)ASCII码值转换成字符函数格式:CHR(<数值表达式>)功能:把<数值表达式>的值转化成相应的ASCII码字符,函数返回值为字符型。说明:<数值表达式>的值必须是0~255之间的整数。【例2.41】
?CHR(86)
&& 结果为
V
(3)数值型转换为字符型函数格式:STR(<数值表达式> [,<长度> [,<小数位数>]])功能:将<数值表达式>的值转换成字符型数据。说明:① 转换时自动进行四舍五入,小数点和负号均计为一位。② 默认<小数位数>,按整数处理;默认<长度>和<小数位数>,结果将只取整数部分,且长度固定为10位。③ 如<长度>值大于转换后的字符串长度,则自动在转换后的字符串前加前导空格以满足规定的<长度>要求。④ 如<长度>值小于<数值表达式>值的整数部分的位数(包括负号),则返回一串星号(*),表示溢出。【例2.42】
X=12345.6789
?STR(X,8,2)
&& 结果为
12345.68(长度8位,小数2位,7以后四舍五入)
?STR(X)
&& 结果为
12346(带5个前导空格)
?STR(X,3)
&& 结果为
***
(4)字符型转换成数值型函数格式:VAL(<字符表达式>)功能:将由数字字符(包括正负号和小数点)组成的字符型数据转换为数值型数据。说明:① 转换时,只要遇到非数字字符就结束转换。若字符串的首字符就不是数字字符,则返回值为0。② 转换后的小数位数默认为2位。【例2.43】
?VAL("12345.678")
&& 结果为
12345.68
?VAL("123S45.6789")
&& 结果为
123.00
?VAL("S12345.6789")
&& 结果为
0.00
(5)字符型转换成日期型函数格式:CTOD(<字符表达式>)功能:将日期形式的字符串转换成日期型数据。说明:<字符表达式>必须是一个有效的日期格式,并与SET DATE命令设置的格式一致。【例2.44】
SET DATE TO MDY
?CTOD("05/20/10")
&& 结果为
05/20/10
SET DATE TO YMD
SET CENTURY ON
?CTOD("2010/05/20")
&& 结果为
2010/05/20
(6)日期型转换成字符型函数格式:DTOC(<日期型表达式>|<日期时间型表达式> [,1])功能:返回对应一个日期或日期时间表达式的字符串。说明:如有[,1]选项,则按照年月日的格式输出。【例2.45】
X=CTOD("05/20/10")
&& 假设当前日期格式为月日年形式
?DTOC(X)
&& 结果为
05/20/10
?DTOC(X,1)
&& 结果为
20100520
2.4.5 测试函数(1)条件测试函数格式:IIF(<逻辑表达式>,<表达式1>,<表达式2>)功能:如<逻辑表达式>的值为真,则函数值为<表达式1>的值,否则为<表达式2>的值。【例2.46】
X=20
&& 把数值20赋值给X
Y=12
&& 把数值12赋值给Y
?IIF(X>Y,50-X,100-Y)
&& 因<逻辑表达式>X>Y的值为真,故结果为30
(2)数据类型测试函数格式:TYPE(<字符型表达式>)功能:测试<字符型表达式>值的数据类型。说明:函数返回一个大写字母,其含义如表2-6所示。表2.6 TYPE函数的返回值及其含义【例2.47】
X=15.25
&& 把数值型常量15.25赋值给X
Y="清华大学"
&& 把字符型常量赋值给Y
Z=.F.
&& 把逻辑型常量赋值给Z
?TYPE("X"),TYPE("Y"),TYPE("Z")
&& 结果为
N
C
L
?TYPE("XYZ")
&& 结果为
U
(3)表文件首测试函数 && 文件首(文件开头,即第一条记录之前)格式:BOF(<工作区号
表别名>)功能:测试当前或指定工作区中表的记录指针是否位于文件首(即第一条记录之前)。若是,返回逻辑真值(.T.);否则返回逻辑假值(.F.)。说明:① 默认参数,默认测试当前工作区中的表文件。② 如指定工作区中没有打开表文件,则函数返回逻辑假值;如表文件中没有任何记录,则函数返回逻辑真值。有关记录指针的概念将在3.4.2节中介绍。【例2.48】
USE E:\VFP6\DATA\学生.DBF
&& 打开名为"学生"的数据表
?BOF()
&& 此时记录指针指向第一条记录,结果为
.F.
SKIP-1
&& 将记录指针移向当前记录(首记录)之前
?BOF()
&& 结果为
.T.
&& 文件尾(文件结束处,即末记录之后)
(4)表文件尾测试函数格式:EOF([<工作区号|表别名>])功能:测试当前或指定工作区中表的记录指针是否位于文件尾(即最后一条记录之后)。若是,则返回逻辑真值(.T.);否则返回逻辑假值(.F.)。说明:如指定工作区中没有打开表文件,则函数返回逻辑假值;如表文件中没有任何记录,则函数返回逻辑真值。【例2.49】
USE E:\VFP6\DATA\学生.DBF
?EOF()
&& 此时记录指针指向第一条记录,结果为
.F.
GO BOTTOM
&& 将记录指针指向最后一条记录
?EOF()
&& 结果为
.F.
SKIP
&& 将记录指针移向当前记录(末记录)之后
?EOF()
&& 结果为
.T.
(5)记录号测试函数格式:RECNO([<工作区号|表别名>])功能:给出当前或指定工作区中表文件当前记录的记录号,函数返回值为数值型。说明:如指定工作区中没有打开表文件,则函数值为0;如记录指针指向文件尾,则函数值为表中的记录数加1;如记录指针指向文件首,则函数值为表中第一条记录的记录号;如表文件中没有任何记录,则函数值为1。【例2.50】
USE E:\VFP6\DATA\学生.DBF
?RECNO()
&& 结果为
1
GO 4
&& 将记录指针移向第4条记录
?RECNO()
&& 结果为
4
GO BOTTOM
&& 将记录指针移向末记录
?RECNO()
&& 结果为
10(假设表中只有10条记录)
SKIP
&& 将记录指针移向当前记录(末记录)之后
?RECNO()
&& 结果为
11
(6)检索测试函数格式:FOUND([<工作区号|表别名>])功能:测试在当前或指定工作区中,用FIND, SEEK, LOCATE等命令对表文件或索引文件的检索是否成功。若成功,则结果为逻辑真值;否则为逻辑假值。(7)测试文件存在函数格式:FILE(<"文件名">)功能:测试指定的文件是否存在。若存在,则返回逻辑真值;否则返回逻辑假值。说明:文件名必须包括扩展名,且文件名两端一定要用西文的引号括起来;如没有引号,系统将默认为是变量名。【例2.51】 假设已在E:\VFP6\DATA文件夹中建立名为“学生.DBF”的表文件,则
?FILE("E:\VFP6\学生.DBF")
&& 结果为
.T.
(8)记录删除测试函数格式:DELETED([<工作区号|表别名>])功能:测试当前或指定工作区中的当前记录是否有删除标记。若有,则返回逻辑真值;否则返回逻辑假值。(9)测试表文件名函数格式:DBF([<工作区号|别名>])功能:返回当前或指定工作区中打开的数据表文件名,返回值为字符型。说明:如在指定工作区中没有打开的表文件,则返回空串。【例2.52】
USE E:\VFP6\DATA\学生.DBF
?DBF()
&& 结果为
E:\VFP6\学生.DBF
(10)检测工作区号函数格式:SELECT([0|1|表别名])功能:返回当前工作区号或者未使用的工作区的最大编号。说明:参数0指定SELECT返回当前工作区号;参数1指定SELECT返回未使用工作区的最大编号;参数“表别名”指定SELECT返回表文件别名所在的工作区编号。函数返回值为数值型。(11)测试表文件是否打开函数格式:USED([工作区|表别名])功能:测试当前或指定的工作区中是否有表文件打开。若有,则返回逻辑真值;否则返回逻辑假值。【例2.53】
USE E:\VFP6\学生.DBF
?USED()
&& 结果为
.T.
2.4.6 其他函数(1)系统函数格式:SYS(<数值表达式>)说明:VFP提供了大量的系统函数SYS( )。根据<数值表达式>值的不同,系统将完成不同的功能。函数返回值为字符型。例如,SYS( )返回机器名和网络机器号,SYS(5)返回当前默认的驱动器名,SYS(2018) 返回最近错误的出错原因信息。(2)消息框函数格式:MessageBox(<字符串表达式1> [,<数值表达式> [,<字符串表达式2>]])功能:显示一个用户自定义对话框,不仅能给用户传递信息,还可以通过用户在对话框上的选择接收用户的响应,作为继续执行程序的依据。说明:① <字符串表达式1>指定对话框中要显示的信息。在字符串中可以含有回车符(CHR(13))以实现多行显示。对话框的高度和宽度将随显示的文本信息的长度自动变化。② <数值表达式>指定对话框的类型参数,对话框类型参数可控制显示在对话框上的按钮和图标的种类及数目,以及焦点选项的按钮。对话框类型参数如表2-7所示。表2.7 对话框类型参数及选项对话框类型参数由三部分组成:按钮类型、图标类型和焦点选项,每一部分只能选择一个值,将三部分的值加在一起就是对话框类型参数的值。如省略该参数,则对话框内只显示一个默认的“确定”按钮,并将此按钮设置为焦点按钮,且不显示任何图标。③ <字符串表达式2>指定对话框的标题内容。若省略该项,对话框标题将显示为“Microsoft Visual FoxPro”。④ 当用户从对话框中选择并单击某一按钮后,函数返回一个值,表示某个按钮被选中,返回值与按钮的关系如表2-8所示。表2.8 MessageBox函数返回值【例2.54】 ?MessageBox("真的要退出吗? ",4+32+0, "提示信息")执行该命令后,将弹出图2.1所示的对话框。图2.1 自定义对话框本节介绍了VFP中常用的一些系统函数。除此之外,VFP还提供了许多功能丰富的系统函数,由于篇幅限制,这里就不一一介绍了。2.5 命令VFP中的各种操作,既可以通过菜单或工具按钮方式完成,也可以通过命令方式完成。无论使用哪种操作,都可以执行VFP的相应命令。前面已经使用过一些简单命令,如显示内存变量信息的DISPLAY MEMORY命令,输出表达式值的?或??命令等。VFP的命令格式通常为:命令动词+修饰子句,即以命令动词开头,辅以若干个修饰和限制的子句。1.命令动词所有命令都以命令动词开头,它决定了该命令的性质。命令动词一般为一个英文动词,表示要执行的命令功能。2.子句子句主要用来修饰或限制命令,通常用于对数据库中的数据操作,有3种形式。(1)范围子句 该子句指明在哪些记录范围内执行命令,可从下面4种范围内选择一种:RECORD <N> 表示指定第N条记录NEXT <N> 表示从当前记录开始的N条记录(不含当前记录)ALL表示数据库的所有记录REST表示从当前记录开始到最后一条记录(不含当前记录)(2)FIELDS子句 该子句后面跟一个字段名列表(字段名之间用逗号隔开),指明对数据表中的哪些字段执行命令。如不选择这个子句,表示对记录中的所有字段执行命令。(3)FOR|WHILE子句 该子句后面跟一个逻辑表达式,表示仅对符合条件(即表达式的结果为.T.)的记录执行命令操作。这两个子句的区别是:FOR子句在整个数据表中对所有记录按条件筛选,对符合条件的记录进行操作;WHILE子句则从当前记录开始按顺序比较条件,对符合条件的记录进行操作,一旦遇到不满足条件的记录就终止命令,不论后面是否还存在符合条件的记录。例如,用命令方式对学生数据表中的记录进行以下操作(设学生表中有学号、姓名、性别和出生日期等字段)。① 显示所有女生的信息:
LIST ALL FOR性别="女"
② 显示从当前记录开始连续5条记录的内容:
LIST NEXT 5
&& 表示从当前记录开始(不含当前记录)的连续5条记录
若当前记录号为4,则执行该命令后将显示记录号为5,6,7,8和9的5条记录内容。③ 显示所有女生的学号、姓名和出生日期:
LIST FIELDS学号,姓名,出生日期
FOR性别="女"
3.命令书写规则使用VFP命令时,一般应遵循以下规则:(1)必须以命令动词开头,命令中可以含有一个或多个子句,子句的顺序任意。(2)命令动词和各子句之间用空格分开(空格数任意)。(3)命令动词可只写不少于前4个字符,且不区分大小写。(4)命令行的最大长度为254个字符,一行写不下时,要在行尾加续行符“;”(西文分号)分行,并在下一行继续书写。本书所给出的命令格式中,方括号([ ])表示可选项,尖括号(< >)表示必选项(具体内容由用户提供),竖杠分隔符(|)表示在其左右参量中任选一项。VFP中提供了大量命令,在后续章节中将具体介绍。本书后的附录中列出了部分常用命令及其功能简介。习题22.1 思考题1. VFP提供了哪几种数据类型?2. 字段变量和内存变量有什么不同?3. 什么是数组?如何定义数组以及为数组元素赋值?4. 如何表示字符型、日期型和逻辑型常量?举例说明。5. 什么是表达式?VFP中有哪几种类型的表达式?6. 如何调用函数?7. 设有如下变量:性别(C)、出生日期(D)、职称(C)、工资(N)、婚否(L),写出符合以下要求的逻辑表达式。(1)工资在1000元与2000元之间(2)年龄在35岁以上的未婚男职工(3)1970年以前出生、工资高于500元但低于1000元的女职工(4)职称是“工程师”或“高工”的已婚女职工2.2 选择题1. 用DIMENSION命令定义了一个数组,其数组元素在未赋值之前的默认值是(  )。(A)不确定(B)0(C).F.(D)" "(空)2. 以下数据中属于字符型数据的是(  )。(A)06/10/02(B)"06/10/02"(C){06/10/02}(D)(06/10/02)3. 若想从字符串“大连市”中取出汉字“连”,应该使用的表达式是(  )。(A)SUBSTR("大连市",2,2)(B)SUBSTR("大连市",2,1)(C)SUBSTR("大连市",3,1)(D)SUBSTR("大连市",3,2)4. 在VFP中,逻辑型、日期型和备注型字段的长度分别是(  )。(A)1,8,128(B)1,8,10(C)1,8,4(D)1,10,45. 以下命令中正确的是(  )。(A)STORE 0 TO X,Y(B)STORE 0,1 TO X,Y(C)X=0,Y=1(D)X=Y=06. 下列函数中,函数值为字符类型的是(  )。(A)CTOD('02/03/98')(B)AT("计算机","全国计算机等级考试")(C)TYPE('2')(D)SUBSTR(DTOC(DATE( )),7)7. 函数TYPE("10/20/99")的值是(  )。(A)10/20/99(B)C(C)D(D)N8. 函数STR(125.86,7,3)的值是(  )。(A)125.86(B)"125.86"(C)125.860(D)"125.87"9. 若M="95.5",则执行命令?20+&M的结果是(  )。(A)2095.5(B)115.5(C)20+&M(D)2010. 以下4个符号中,表示常量的是(  )。(A)F(B)BOTTOM(C).F.(D)TOP11. 设工资=640,职称="副教授",性别="男",则结果为假的逻辑表达式是(  )。(A)工资>500 .AND. 职称="副教授" .AND. 性别="男"(B)性别="女" .OR. .NOT.职称="助教"(C)工资>550 .AND. 职称="副教授" .OR.职称="讲师"(D)工资=550 .AND.(职称="教授".OR. 性别="男")12. 下列字段名或变量名中不正确的是(  )。(A)2CLIEN_ID(B)姓名(C)COLOR_CODE(D)年龄13. 执行SET EXACT OFF命令后,下列表达式的结果为真的是(  )。(A)"上海"="上海市"(B)"上海市"="上海"(C)"上海市"=="上海"(D)"上海"=="上海市"14. 以下日期值正确的是(  )。(A){^2002-03-20}(B){"2002-03-20"}(C){2002-03-20}(D)(2002-03-20)2.3 填空题1. 如打开一个空数据表文件,用函数RECNO( )测试,其结果一定是_____。2. 若ABC="伟大的祖国",则?SUBSTR(ABC,LEN(ABC)/5+1,4)的结果为_____。3. 当内存变量名与数据表中的字段变量名相同时,要访问该内存变量,必须在变量名前加上前缀______,否则系统将优先访问同名的字段变量。4. 执行DIMENSION X(3,4)命令之后,数组X中的元素个数是______。5. 若X="12345",则执行命令?TYPE("&X")的结果是______。6. 设X=2,则执行命令?X=X+1的结果是______。7. 设当前日期为2002年8月4日,则在VFP中用严格的日期格式表示为______。8. 设当前日期格式为月日年,若要改为年月日的格式,应使用命令______。9. 内存变量的数据类型由 决定______,可以把不同类型的数据赋给同一个变量。10. TIME( )函数返回值的数据类型是______。2.4 上机练习题1. 变量操作(1)内存变量的赋值和显示。在命令窗口中定义下述变量,并执行相应的操作。
CLEAR MEMORY
X1=4*25
X2="ABC"
X3={^2002-03-20}
STORE .F. TO Y1,Y2
?X1,X2,X3,Y1,Y2
DISPLAY MEMORY
LIST MEMORY LIKE X*
LIST MEMORY LIKE ?2
(2)数组的定义及赋值操作。在命令窗口中定义两个数组变量,并执行相应的操作。
CLEAR MEMORY
DIMENSION
A1(5),A2(2,3)
STORE 0 TO A1
A1(2)= "HELLO"
A2(1,3)=10.5
A2(2,1)= "MORNING"
LIST MEMORY LIKE A?
2. 函数与表达式操作。在命令窗口中输入下列命令,按回车键执行。(1)
性别="男"
年龄=25
职称="助教"
工资=1500
婚否=.F.
? 年龄>25.AND. 职称="助教"
? 年龄<25
.OR. 工资<2000
.AND.
.NOT.
职称="讲师"
? 性别="女"
.AND.
(职称="讲师"
.OR.
.NOT.
婚否)
? 性别="女"
.AND.
职称="讲师"
.OR.
.NOT.
婚否
(2)
A=5
B=STR(A,1)
C="学生&B"
?A,B,C
(3)
SET DATE TO MDY
出生日期=CTOD("03/20/96")
?STR(YEAR(出生日期),4)+ "年"+STR(MONTH(出生日期),2)+ "月";
+STR(DAY(出生日期),2)+ "日"
(4)
X=SUBSTR("12340.5",4,4) - "5"
Y=RIGHT(X,4)
?X,Y,&X+&Y

本文已收录GitHub,更有互联网大厂面试真题,面试攻略,高效学习资料等
大概十年前,我在阿里巴巴工作的时候,曾经和另一个面试官一起进行一场技术面试,面试过程中我问了一个问题:Hash 表的时间复杂度为什么是 O(1)?候选人没有回答上来。面试结束后我和另一个面试官有了分歧,我觉得这个问题没有回答上来是不可接受的。而他则觉得,这个问题有一点难度,回答不上来不说明什么。因为有了这次争执,后来这个问题成了我面试时的必考题。此后十年间,我用这个问题面试了大约上千人,这些面试经历让我更加坚定了一个想法:这个问题就是候选人技术水平的一个分水岭,是证明一个技术人员是否具有必备专业技能和技术悟性的一个门槛。这个槛过不去是不可接受的。为什么呢?我很难相信,如果基本的数据结构没有掌握好,如何能开发好一个稍微复杂一点的程序?要了解 Hash 表,需要先从数组说起。一、数组数组是最常用的数据结构,创建数组必须要内存中一块连续的空间,并且数组中必须存放相同的数据类型。比如我们创建一个长度为 10,数据类型为整型的数组,在内存中的地址是从 1000 开始,那么它在内存中的存储格式如下。由于每个整型数据占据 4 个字节的内存空间,因此整个数组的内存空间地址是 1000~1039,根据这个,我们就可以轻易算出数组中每个数据的内存下标地址。利用这个特性,我们只要知道了数组下标,也就是数据在数组中的位置,比如下标 2,就可以计算得到这个数据在内存中的位置 1008,从而对这个位置的数据 241 进行快速读写访问,时间复杂度为O(1)。随机快速读写是数组的一个重要特性,但是要随机访问数据,必须知道数据在数组中的下标。如果我们只是知道数据的值,想要在数组中找到这个值,那么就只能遍历整个数组,时间复杂度为 O(N)。二、链表不同于数组必须要连续的内存空间,链表可以使用零散的内存空间存储数据。不过,因为链表在内存中的数据不是连续的,所以链表中的每个数据元素都必须包含一个指向下一个数据元素的内存地址指针。如下图,链表的每个元素包含两部分,一部分是数据,一部分是指向下一个元素的地址指针。最后一个元素指向 null,表示链表到此为止。因为链表是不连续存储的,要想在链表中查找一个数据,只能遍历链表,所以链表的查找复杂度总是 O(N)。但是正因为链表是不连续存储的,所以在链表中插入或者删除一个数据是非常容易的,只要找到要插入(删除)的位置,修改链表指针就可以了。如图,想在 b 和 c 之间插入一个元素 x,只需要将 b 指向 c 的指针修改为指向 x,然后将 x 的指针指向 c 就可以了。相比在链表中轻易插入、删除一个元素这种简单的操作,如果我们要想在数组中插入、删除一个数据,就会改变数组连续内存空间的大小,需要重新分配内存空间,这样要复杂得多。三、Hash表前面说过,对数组中的数据进行快速访问必须要通过数组的下标,时间复杂度为 O(1)。如果只知道数据或者数据中的部分内容,想在数组中找到这个数据,还是需要遍历数组,时间复杂度为 O(N)。事实上,知道部分数据查找完整数据的需求在软件开发中会经常用到,比如知道了商品ID,想要查找完整的商品信息;知道了词条名称,想要查找百科词条中的详细信息等。这类场景就需要用到 Hash 表这种数据结构。Hash 表中数据以 Key、Value 的方式存储,上面例子中,商品 ID 和词条名称就是 Key,商品信息和词条详细信息就是 Value。存储的时候将 Key、Value 写入 Hash 表,读取的时候,只需要提供 Key,就可以快速查找到Value。Hash 表的物理存储其实是一个数组,如果我们能够根据 Key 计算出数组下标,那么就可以快速在数组中查找到需要的 Key 和 Value。许多编程语言支持获得任意对象的HashCode,比如 Java 语言中 HashCode 方法包含在根对象 Object 中,其返回值是一个Int。我们可以利用这个 Int 类型的 HashCode 计算数组下标。最简单的方法就是余数法,使用 Hash 表的数组长度对 HashCode 求余, 余数即为 Hash 表数组的下标,使用这个下标就可以直接访问得到 Hash 表中存储的 Key、Value。上图这个例子中,Key 是字符串 abc,Value 是字符串 hello。我们先计算 Key 的哈希值,得到 101 这样一个整型值。然后用 101 对 8 取模,这个 8 是哈希表数组的长度。101 对 8取模余 5,这个 5 就是数组的下标,这样就可以把 (“abc”,“hello”) 这样一个 Key、Value 值存储在下标为 5 的数组记录中。当我们要读取数据的时候,只要给定 Key abc,还是用这样一个算法过程,先求取它的HashCode 101,然后再对 8 取模,因为数组的长度不变,对 8 取模以后依然是余 5,那么我们到数组下标中去找 5 的这个位置,就可以找到前面存储进去的 abc 对应的 Value值。但是如果不同的 Key 计算出来的数组下标相同怎么办?HashCode101 对 8 取模余数是5,HashCode109 对 8 取模余数还是 5,也就是说,不同的 Key 有可能计算得到相同的数组下标,这就是所谓的 Hash 冲突,解决 Hash 冲突常用的方法是链表法。事实上,(“abc”,“hello”) 这样的 Key、Value 数据并不会直接存储在 Hash 表的数组中,因为数组要求存储固定数据类型,主要目的是每个数组元素中要存放固定长度的数据。所以,数组中存储的是 Key、Value 数据元素的地址指针。一旦发生 Hash 冲突,只需要将相同下标,不同 Key 的数据元素添加到这个链表就可以了。查找的时候再遍历这个链表,匹配正确的 Key。如下图:因为有 Hash 冲突的存在,所以“Hash 表的时间复杂度为什么是 O(1)?”这句话并不严谨,极端情况下,如果所有 Key 的数组下标都冲突,那么 Hash 表就退化为一条链表,查询的时间复杂度是 O(N)。但是作为一个面试题,“Hash 表的时间复杂度为什么是O(1)”是没有问题的。四、栈数组和链表都被称为线性表,因为里面的数据是按照线性组织存放的,每个数据元素的前面只能有一个(前驱)数据元素,后面也只能有一个(后继)数据元素,所以称为线性表。但是对数组和链表的操作可以是随机的,可以对其上任何元素进行操作,如果对操作方式加以限制,就形成了新的数据结构。栈就是在线性表的基础上加了这样的操作限制条件:后面添加的数据,在删除的时候必须先删除,即通常所说的“后进先出”。我们可以把栈可以想象成一个大桶,往桶里面放食物,一层一层放进去,如果要吃的时候,必须从最上面一层吃,吃了几层后,再往里放食物,还是从当前的最上面一层放起。栈在线性表的基础上增加了操作限制,具体实现的时候,因为栈不需要随机访问、也不需要在中间添加、删除数据,所以可以用数组实现,也可以用链表实现。那么在顺序表的基础上增加操作限制有什么好处呢?在之前的文章中提到的程序运行过程中,方法的调用需要用栈来管理每个方法的工作区,这样,不管方法如何嵌套调用,栈顶元素始终是当前正在执行的方法的工作区。这样,事情就简单了。而简单,正是我们做软件开发应该努力追求的一个目标。五、队列队列也是一种操作受限的线性表,栈是后进先出,而队列是先进先出。在软件运行期,经常会遇到资源不足的情况:提交任务请求线程池执行,但是线程已经用完了,任务需要放入队列,先进先出排队执行;线程在运行中需要访问数据库,数据库连接有限,已经用完了,线程进入阻塞队列,当有数据库连接释放的时候,从阻塞队列头部唤醒一个线程,出队列获得连接访问数据库。在之前文章中讲解堆栈的时候,举了一个大桶放食物的例子,事实上,如果用这种方式存放食物,有可能最底下食物永远都吃不到,最后过期了。现实中也是如此,超市在货架上摆放食品的时候,其实是按照队列摆放的,而不是堆栈摆放的。工作人员在上架新食品的时候,总是把新食品摆在后面,使食品成为一个队列,以便让以前上架的食品被尽快卖出。六、树数组、链表、栈、队列都是线性表,也就是每个数据元素都只有一个前驱,一个后继。而树则是非线性表,树是这样的。软件开发中,也有很多地方用到树,比如我们要开发一个 OA 系统,部门的组织结构就是一棵树;我们编写的程序在编译的时候,第一步就是将程序代码生成抽象语法树。传统上树的遍历使用递归的方式,而我个人更喜欢用设计模式中的组合模式进行树的遍历。七、总结这是一篇关于数据结构的文章,面试中问数据结构是一个非常有意思的话题,很多拥有绚丽简历和多年工作经验的候选人在数据结构的问题上翻了船,这些人有时候会解释说,这些知识都是大学时学过的,工作这些年用不着,记不太清楚了。事实上,我很难相信,如果这些基本数据结构没有掌握好,如何能开发好一个稍微复杂一点的程序。但欣慰的是,在这些年的面试过程中,我发现候选者中能够正确回答基本数据结构问题的比例越来越高了,我也越来越坚定用数据结构问题当做是否跨过专业工程师门槛的试金石。作为一个专业软件工程师,不管有多少年经验,说不清楚基础数据结构的工作原理是不能接受的。

我要回帖

更多关于 将一个数组的值赋值给另一个数组 的文章