第三章数据与数据运算
(占考试笔试分值8至16分[一般是4-8道题])
在VFP中,除了能够对数据表中的数据进行处理,也可以对诸如常量、内存变量等数据表之外的数据进行单独处理。简单的数据处理可以通过函数、表达式和单条命令完成,复杂的数据处理则可能需要编写程序来完成。
本章主要学习VFP的常量、内存变量、表达式和常用函数。
3.1 常量与变量
常量通常是指以文字串形式出现在代码中的数据,代表一个具体的、不变的值。变量用于存储数据,一个变量在不同的时刻可以存放不同的数据。常量、变量类型包括数值型(N)、货币型(Y)、字符型(C)、日期型(D)、日期时间型(T)、逻辑型(L)六种。
3.1.1 常量
例如:’我是”长沙”人’?len("")为0, ?len(" ")为4。
?() 换行显示下一个?()的值;??()不换行显示下一个??()的值。
4.日期型常量
有两种书写格式,既严格日期格式和传统日期格式,其定界符都是一对花括号。花括号内年、月、日间用斜杠(/)、连字号(-)、句点(.)或空格做分隔符分隔。
例如:?2012-12-12 显示为1988,意思是数字相减。
?{^2011-10-12}或?{^2011.10.12}或?{^2011/10/12} 才显示为:10/12/11
标准日期的运算:?{^2011/10/12}-{^2009.03.03} 显示为953,表示相差953天。
?{^2009.03.03}+953 显示为{^10/12/11} 表示09年3月3日加上953天。
例如:直接执行命令:?{02/05/97} 会弹出提示错误窗口:
必须在执行命令前先设置系统状态:set strictdate to 0
set strictdate to 0
?{02/05/97} 才能显示02/05/97
如果执行SET MARK TO 没有指定任何分隔符,表示恢复系统默认的斜杠分隔符。
其默认值为AMERICAN
例如:SET DATE TO “YMD”
?{^2012/05/14} 则显示12/05/14
③SET CENTURY ON|OFF|TO[<世纪值>[ROLLOVER <年份参照值>]] 功能:设置日期年份
ON 显示世纪,即用4位数字表示年份。
例如:SET CENTURY ON
?{^2012/05/14}
显示结果为:2012/05/14
OFF 不显示世纪,即用2位数字表示年份。它是系统默认的设置。
SET CENTURY OFF
?{^2012/05/14}
显示结果为: 12/05/14
TO 决定如何解释一个用2位数字年份表示的日期所处的世纪。具体来说,如果该日期的2位数字年份大于等于<年份参照值>,则它所处的世纪即为<世纪值>;否则为<世纪值>+1。
例如:SET CENTURY to 19 rollover 51 && 世纪值为19,年份参照值为51。
SET CENTURY on && 显示世纪
?{^52/05/14}
显示结果为:1952/05/14 && 52年份值大于年份参照值51,所以显示的世纪值为19。
如果:?{^49/05/14}
则显示结果为:2049/05/14 && 49年份值小于年份参照值51,所以显示的世纪值为20。
CTOD表示将字符串转换成日期函数;CTOT表示返回日期时间值函数。
set strictdate to 0 set strictdate to 1 set strictdate to 2
例:设置不同的日期格式,在命令窗口键入如下四条命令,并分别回车执行:
SET CENTURY ON && 设置4位数字年份
SET MARK TO && 恢复系统默认的斜杠日期分隔符
SET DATE TO YMD && 设置“年月日“的格式
?{^2001-08-26}
主窗口显示: 2001/08/26
再在命令窗口键入如下四条命令,并分别回车执行:
SET CENTURY OFF &&设置2位数字年份
SET MARK TO “.” && 设置日期分隔符为西文句号
SET DATE TO MDY && 设置“月日年“的格式
? {^2001-08-26}
主窗口显示: 08.26.01
接着在命令窗口中键入如下两条命令,并分别回车执行:
SET STRICTDATE TO 0 &&不进行严格的日期格式检测
? {^2001-08-26},{09.22.01}
主窗口显示: 08.26.01 09.22.01
在命令窗口键入如下两条命令,并分别回车执行:
SET MARK TO “;” &&设置日期分隔符为分号
? {^2001-08-26},{09.22.01}
主窗口显示: 08;26;01 09;22;01
? .T. 显示.T. ?.Y.也是显示.T. ? .F.或? .N. 都显示为.F.
3.1.2 变量
内存变量是表结构之外独立存在于内存中的变量。内存变量可用来存储数据,定义内存变量时需为它取名并赋初值,内存变量建立后存储于内存中。
例如:打开数据库中的“档案“表,在命令窗口中输入:? 姓名
那么在屏幕上就会显示当前指针指向的记录的姓名:李军
注意:? 姓名中的姓名并不需要加引号,因为这里的姓名为变量。加了引号就是常量了。屏幕显示就会变成“姓名“而不是档案表中的指针指向的记录的姓名“李军”了。
例如:在命令窗口中输入: AB=100 (回车)
? AB (回车)
屏幕中就会显示: 100
在命令窗口中输入:AD=5+6 (回车)
?AD (回车)
屏幕中就会显示: 11
在命令窗口中输入:STORE 20 TO AB,AC,AD (回车)
? AB,AC,AD
屏幕中就会显示: 20 20 20
例如:如果定义内存变量姓名=”XYZ”,与打开的档案表中的姓名字段变量同名,则:
? 姓名屏幕显示为当前指针所指记录的姓名: 李军
? M.姓名或? M->姓名屏幕才会显示内存变量XYZ。
当然如果没有打开“档案”表的话使用 ? 姓名则会显示内存变量 XYZ。
A)D、L、Y、N、C B)T、L、Y、N、C
C)T、L、N、Y、C D)T、L、Y、N、S
DIMENSION :建立数组 DECLARE :建立内存变量数组
以上两种格式的功能完全相同。数组创建后,系统自动给每个数组元素赋以逻辑假.F.。
例如,命令DIMENSION AD(5),Y(2,3)定义了两个数组:
一维数组AD含5个元素:AD(1)、AD(2)、AD(3)、AD(4)、AD(5)
二维数组Y含6个元素: Y(1,1)、Y(1,2)、Y(1,3)、Y(2,1)、Y(2,2)、Y(2,3)。
且?AD(1)-?AD(5)的初始值都为F。如果输入?AD(6),则弹出提示框:
如果进行赋值,如:AD(1)=58 ?AD(1) 则屏幕显示 58。
如果赋值为:AD=0,则AD(1)- AD(5)的值全部为0。
比如在同一环境中已经建立了一个简单内存变量AD,那么就不能再建立一个数组名也为AD的数组了。
例如:不能使用AC=AD+1的表达示,可以使用AC=AD(3)+1的表达示。
定义二维数组:如DIME DB(2,3),则含有DB(1,1)、DB(1,2)……DB(2,3)六个元素。如果赋值为 DB (2,1)=52
? DB(2,1)或 ? DB(4)
屏幕都显示为 52
3.1.3 内存变量常用命令
例如: STORE 20 TO AB,AC,AD 回车
? AB 回车
屏幕显示:20
? AC 回车
屏幕换一行显示:20
如果 ?? AB 回车
屏幕显示:20
?? AC 回车
屏幕不换行显示:20
例如:先定义内存变量,在命令窗口中输入:
AB=15 回车
LIST MEMORY LIKE AB 回车
屏幕就会显示:
它显示的这些分别表示:
AB 是变量名,Pub表示作用范围,PUBLICK的省些,表示公共变量,在编程中会学习到。 N 表示数据类型,数值型。 15 是变量值。
AC=”ABCDE”回车
LIST MEMORY LIKE AC 回车
屏幕会显示:
AC是变量名,Pub表示作用范围,C 表示数据类型,字符型。”ABCDE”为变量值。
例如:LIST MEMORY LIKE A* 屏幕会显示:
LIST MEMORY LIKE A? 屏幕会显示:
例如: LIST MEMORY LIKE A* TO FILE ABC
在输出到窗口的同时还会存入到指定的文件名为ABC的文本文件中,打开ABC的文本文件:
例如: DISPLAY MEMORY LIKE A* 同样会显示:
DISPLAY与LIST命令的区别是,DISPLAY能暂停,按任意键显示下一屏,而LIST不能。
例如:LIST MEMORY 显示内存中的所有变量,屏幕没有暂停,一下就跳过去了。
而DISPLAY MEMORY显示内存中的所有变量的时候,在显示完一屏后就会暂停,并弹出一个提示窗口:
RELEASE AD 回车
LIST MEMORY LIKE A* 回车
这时候内存变量AD就被清除了:
RELEASE ALL LIKE A* 表示清除以A开头的所有内存变量
RELEASE ALL EXCEPT A* 表示清除除了以A开头的所有内存变量。
3.2 表达式
3.2.1 数值、字符与日期时间表达式
求余运算:
求余运算%和取余函数MOD()的作用相同,结果的正负号与除数一致。如果被除数与除数同号,那么
运算结果即为两数相除的余数;如果被除数与除数异号,则运算结果为两数相除的余数再加上除数的值。当表达式中出现乘(*)、除(/)和求余运算(%)时,它们具有相同的优先级,依次从左至右计算。
例如:求余运算示例:
? 15%4,15%-4
结果为: 3 -1
a="Hello " (尾部包含一个空格) b="everyone!"
?a+b,a-b,len(a+b),len(a-b) 屏幕显示为:
Hello everyone! Helloeveryone! 15 15
? {^2001-03-19}+10,{^2001-03-19}-{^2000-03-19}
结果为: 03/29/01 365
? {^2001-03-19 11:10:10 AM}-{^2001-03-19 10:10:10 AM}
结果为: 3600
?{^2001-03-19 11:10:10 AM}+10
结果为:03/19/01 11:10:20 AM
3.2.2 关系表达式
例如:? 5<4 结果为 .F. ? 5>4结果为 .T. ? 5=5 结果为 .T. ? 5<>5结果为 .F.
字符型的比较: ?”张三”>”李四”结果为 .T.
默认的是比较姓名的第一个的拼音的第一个字母,张三的张的拼音第一个字母Z,李四的李的拼音第一个字母是L,在字母表中,Z在L的后面,所以Z要比L大,即“张三“>“李四”。
?”张三”>”张五”结果为.F.
因为当字符型的第一个相同时,就比较第二个的拼音的第一个字母,三的第一个字母为S,五的第一个字母为W。W在S的后面,所以,”张三”<”张五”
?”张三丰”=”张三”结果为.T.
字符表达式默认是从后面和前面对应的进行比较,比较完后就结束了,所以当后面的“张三”和前面的“张三丰”中的“张三”比较完后就结束了。
?"张三"="张三丰" 结果为.F.
后面的字符串"张三丰"中的“张三”和前面的字符串“张三”虽然对应相同,但“丰”没有与之对应的字符,所以为假。
但如果使用 ?”张三丰”==”张三”结果为.F.
因为这是精确比较,两边的字符串必须一样才能是真。
包含测试$的应用:
例如:?”AB”$”CDYGABDIC”结果为.T.
而 ?"AB"$"CDYGADBIC" 结果为.F. 虽然后面的字符串中有A和B,但并没有“AB”。
注意,数值型比较中 ?258>85结果为.T.
如果 ?”258”>”85”结果为.F.因为是字符型,先比较第一个字符:2<8的。
默认是拼音,也可以是笔画(Stroke)和机器内码(Machine)。
例如,在默认状态下为 SET EXACT OFF(不精确比较)
?“张三是中国人”=”张三”结果为.T.
如果设置为SET EXACT ON (精确比较)
SET EXACT ON
?“张三是中国人”=”张三”结果就为.F.了。
3.2.3 逻辑表达式
例如 AB=20
? AB>=10 AND AB<=30 结果为.T.
? AB>=10 结果为.T.
? .NOT.AB>=10 结果为.F.
? !AB>=10 结果为.F.
? AB<=0 OR AB>=10 结果为.T.(只需要一个是真的就是真,而AND要都为真表达式才为真)
3.3 常用函数
3.3.1 数值函数
例: STORE 10 TO X 回车
? ABS(5-X), ABS(X-5),SIGN(5-X),SIGN(X-10),SIGN(X-5)
5 5 -1 0 1
例:STORE -100 TO X
? SIGN(X)*SQRT(ABS(X))
-10.00
例:STORE 5.8 TO X
? INT(X),INT(-X),CEILING(X),CEILING(-X),FLOOR(X),FLOOR(-X)
5 -5
6 -5 5 -6
例:X=345.345
? ROUND(X,2),ROUND(X,1),ROUND(X,0),ROUND(X,-1)
345.35 345.3 345 350
<数值表达式1>是被除数,<数值表达式2>是除数。余数的正负号与除数相同。如果被除数与除数同号,那么函数值即为两数相除的余数;如果被除数与除数异号,则函数值为两数相除的余数再加上除数的值。
例:? MOD(10,3),MOD(10,-3),MOD(-10,3),MOD(-10,-3)
1 -
2 2 -1
自变量中所有的表达式类型必须一致。
例:? MAX(“2”,”12”,”05”),MIN(“汽车”,”飞机”,“轮船“) 2 飞机
3.3.2 字符函数
? len (space(4))
显示结果为:4
例:STORE SPACE(1)+”TEST”+SPACE(3)TO SS
? TRIM(SS)+ LTRIM(SS)+ ALLTRIM(SS)
TESTTEST TEST && 中间有3个空格
? LEN(SS),LEN(TRIM(SS)),LEN(LTRIM(SS)),LEN(ALLTRIM(SS))
8 5 7 4
例:STORE “GOOD BYE!” TO X
? LEFT(X,2),SUBSTR(X,6,2)+SUBSTR(X,6),RIGHT(X,3)
GO BYBYE! YE!
例:STORE “abracadabra”TO S
? OCCURS("a",S),OCCURS("b",S), OCCURS("c",S), OCCURS("e",S)
5 2 1 0
例: STORE “This is visual FoxPro”TO x
? AT("fox",x),ATC("fox",x),AT("is",x,3),AT("xo",x) && AT("is",x,3)表示”is”在X中第三次出现的位置。
0 16 10 0
功能:用<字符表达式2>值替换<字符表达式1>中由<起始位置>和<长度>指明的一个子串。替换和被替换的字符个数不一定相等。如果<长度>值是0,则相当于在<字符表达式1>中由<起始位置>指定的字符前面插入<字符表达式2>。如果<字符表达式2>值是空串,则相当于在<字符表达式1>中删去<起始位置>和<长度>指明的字串。
例:STORE “GOOD BYE!”TO S1
STORE “MORNING”TO S2
? STUFF(S1,6,3,S2),STUFF(S1,1,4,S2)
GOOD MORNING! MORNING BYE!
该函数的自变量是三个字符表达式。当第一个字符串中的一个或多个相同字符与第二个字符串中的某个字符相匹配时,就用第三个字符串中的对应字符(与第二个字符串中的那个字符具有相同位置)替换这些字符。如果第三个字符串包含的字符个数少于第二个字符串包含的字符个数,导致没有对应字符,那么第一个字符串中相匹配的各字符将被删除。如果第三个字符串包含的字符个数多余第二个字符串包含的字符个数,多余字符被忽略。
例: X1=CHRTRAN(“ABACAD”,”ACD”,”X12”)
Y1= CHRTRAN(“计算机ABC”,”计算机”,”电脑”)
Z1= CHRTRAN("大家好!","大家","您")
? X1,Y1,Z1
XBX1X2 电脑ABC 您好!
例:STORE “abc” TO X
STORE “abcd”TO Y
? LIKE ("ab*",x),LIKE("ab*",y),LIKE(x,y),LIKE("?b?",x),LIKE("Abc",x) .T. .T. .F. .T. .F.
A)EMPTY(.NULL.) B)LIKE(‘XV?’.‘XVZ’)
C)AT(‘XV’.’abcxvz’) D)ISNULL(SPACE(0))
3.3.3 日期时间函数
例:? DATE(), TIME(),DATETIME()
例: STORE {^2001-08-18} TO d
? YEAR(d),MONTH(d),DAY(d)
2001 8 18
这三个函数的返回值都是数值型。
这三个函数的返回值都是数值型。
例: STORE {^2001-03-18 02:30:50 P} TO t
? HOUR(t),MINUTE(t),SEC(t)
14 30 50
3.3.4 数据类型转换函数
功能:将<数值表达式>的值转换成字符串,转换时根据需要自动进行四舍五入。返回字符串的理想长度L应该是 <数值表达式>值的整数部分位数加上<小数位数>值,再加上1位小数点。如果<长度>值大于L,则字符串加前导空格以满足规定的<长度>要求;如果<长度>值大于等于<数值表达式>值的整数部分位数(包含负号)但又小于L,则优先满足整数部分而自动调整小数位数;如果<长度>值小于<数值表达式>值的整数部分位数,则返回一串星号(*)。<小数位数>的默认值为0,<长度>的默认值为10。
例: STORE -123.456 TO n
? “n=”+ STR(n,8,3)
n=-123.456
? STR(n,9,2),STR(n,6,2),STR(n,3),STR(n,6),STR(n)
-123.46 -123.5 *** -123(小数位默认值是0,无小数位) -123(长度默认值为10)
功能:将由数字符号<包括正负号、小数点>组成的字符型数据转换成相应的数值型数据。若字符串内出现非数字字符,那么只转换前面部分;若字符串的首字符不是数字符号,则返回数值零,但忽略前导空格。
例: STORE “-123.”TO x
STORE ”45” TO y
STORE “A45”TO z
? VAL(x+y),VAL(x+z),VAL(z+y)
-123.45 -123.00 0.00
字符串中的日期部分格式要与SET DATE TO 命令设置的格式一致,其中的年份可以用4位,也可以用两位。如果用两位,则世纪由SET CENTURY TO 语句指定。
例: SET DATE TO YMD
SET CENTURY ON && 显示日期或日期时间时,用4为数显示年份
SET CENTURY TO 19 ROLLOVER 51
d1 = CTOD(“2001/03/18”)
t1 = CTOD(“2001/03/18”+””+TIME())
? d1,t1,CTOD(“50/01/01”),CTOD(“51/01/01”)
2001/03/18 2001/03/18 10:31:54 PM 2050/01/01 1951/01/01
结果字符串中日期部分的格式与SET DATE TO 语句的设置和SET CENTURY ON | OFF(ON为4位数年份,OFF为两位数年份)语句的设置有关。结果字符串中时间部分的格式受SET HOURS TO 12|24语句的设置影响。
对DTOC()来说,如果使用选项1,则结果字符串的格式总是为YYYYMMDD,共8个字符。对TTOC()来说,如果使用选项1,则结果字符串的格式总是YYYYMMDDHHMMSS,采用24小时制,共14个字符。
例: STORE DATETIME() TO t
? t
02/26/12 01:15:04 PM
? DTOC(t),DTOC(t,1),TTOC(t),TTOC(t,1)
02/26/12 20120226 02/26/12 01:15:04 PM 20120226131504
如果该函数与其后的字符无明确分界,则要用“.”作为函数结束标识。宏替换可以嵌套使用。
例:在打开数据库的情况下:
STORE “学籍” TO DB
USE &DB && 相当于USE 学籍
XM=”姓名” && 相当于?XM,姓名
? XM,&XM
姓名李丽
3.3.5 测试函数
如果<表达式L>或<表达式H>有一个是NULL值,那么函数值也是NULL值。
例: STORE .NULL. TO x
STORE 100 TO y
? BETWEEN(150,y,y+100),BETWEEN(90,x,y)
.T. .NULL.
例: STORE .NULL. TO X
? X, ISNULL(X)
.NULL. .T.
需要注意的是,这里所指的“空”值与NULL值是两个不同的概念。函数EMPTY(.NULL.)的返回值为逻辑假(.F.)。其次,该函数自变量表达式的类型可以是数值型、字符型、逻辑型、日期型等类型,不同类型数据的“空”值,有不同的规定,如下表:
不同类型数据的“空”值规定
字母的含义如下表所示:
用VARTYPE()测得的数据类型
若<表达式>的运算结果是NULL值,则函数根据<逻辑表达式>值决定是否返回<表达式>的类型:如果<逻辑表达式>的值为.T.,就返回<表达式>的类型;如果<逻辑表达式>的值为.F.或缺省,则返回X以表明<表达式>的运算结果是NULL值。
若<表达式>是一个数组,则函数根据第一个数组元素的类型返回字符串。
例: X=”123”
STORE 10 TO Y
STORE .NULL. TO X
STORE $ 100.2 TO Z
? VARTYPE(X), VARTYPE(X,.T.), VARTYPE(Y), VARTYPE(Z)
X C N Y
例:USE 档案
GO BOTTOM
? EOF()
.F.
SKIP
? EOF(),EOF(2) && 假定2号工作区没有打开表
.T. .F.
,表文件首是指第一条记录的前面位置。若指定工作区上没有打开表文件,函数返回逻辑值(.F.);若表文件中不包含任何记录,函数返回逻辑真(.T.)
功能:返回当前表文件(若缺省自变量)或指定表文件中当前记录(记录指针所指记录)的记录号。如果指定工作区上没有打开表文件,函数值为0。如果记录指针指向文件尾,函数值为表文件中的记录数加1。如果记录指针指向文件首,函数值为表文件中第一条记录的记录号。
功能:返回当前表文件(若缺省自变量)或指定表文件的记录个数。如果指定工作区上没有打开表文件,函数值为0。
RECCOUNT()返回的是表文件中物理上存在的记录个数。不管记录是否被逻辑删除以及SET DELETED的状态如何,也不管记录是否被过滤(SET FILTER),该函数都会把它们考虑在内。
<表达式1>和<表达式2>的类型不要求相同。
例: X=100
Y=300
? IIF(X>100,X-50,X+50),IIF(Y>100,Y-50,Y+50)
150 250
SET CENTURY ON
STORE DATE() TO d
STORE DTOC(d) TO s
? s, IIF(LEN(s)=8,"这是两位数年份","年份是:"+STR(YEAR(d),4))
02/26/2012 年份是:2012
功能:测试当前表文件或指定表文件中的当前记录(记录指针所指记录)是否有删除标记“*“。若有就返回逻辑真,否则返回逻辑假。
功能:当使用LOCATE或CONTINUE命令查找到表中满足条件的记录时,函数值为真,否则为假。