WMLScript脚本程序设计
作为一种编辑语言,WMLScript提供了强大的函数、语句和库功能,以及外部编辑、访问控制等支持,同时对程序运行中可能产生的错误给出了检测手段和具体的解决办法。这些内容属于WMLScript的脚本程序设计知识和进一步的编程规定,我们本章就对此进行详细介绍。
5.1 语句
前面我们学习了变量、操作符和表达式,但仅由这些内容并不能完成某个完整的功能,因为他们不能形成完整的操作或处理程序。变量就如同与严重的单词,表达式如语言中的词组,他们都不能表达一个完整的意思;只有语句,是语言中完整的句子,能够表达完整的意思并实现某个完整的功能。WML Script提供了丰富的语句功能,使用这些语句我们可以在WML的卡片中建立交互功能和其他需要的复杂功能。
在WML Script中,每条语句的后面都需要以一个分号(;)结尾。为了养成严谨的编程风格,建议大家编写脚本时,语句后一定要加上分号(;),这也有助于我们形成一种良好的编程习惯。
WML Script语句的书写和排列格式比较自由。我们可以在同一程序行中连续写上多个语句,也可以把同一语句分成多行排列。WML Script将根据分号(;)来确定语句的具体内容。
WML Script的语句主要包括两类。第一类是基本语句,如空语句、表达式语句、块语句、变量语句和return语句等;第二类是条件语句,如if语句;第三类是循环语句,如while语句、for语句、break语句和continue语句等。下面我们分别讲解这些语句的语法、功能和使用方法。
5.1.1 基本语句
WML Script基本语句主要用于程序格式控制和变量声明,其中有些语句我们已经不太陌生了。
空语句
空语句用于定义一个空的程序行,它没有任何标识符和操作符,也不执行任何操作。它只是以分号(;)结束。其语法格式为:
;
显然,空语句是一种十分特殊的语句。由是我们为了让程序具有更好的可读性,通常在程序中的适当地方加上几个空语句,以起到分隔或突出的作用。例如,下面的几行程序中就含有一个空语句:
str=\"Hello\";
val=25;
;
MyVal=val*val+5;
alert(\"Hi,Hi!!!\");
再如,while语句用于判断一个条件并在条件满足的时候执行相应的任务,但如果希望条件满足的时候什么也不作,那么就可以给它配上一个空语句,使之条件满足的执行空操作:
while(!poll(device));
这实际上是while语句和空语句组成的两条语句。其中的分号(;)在这里就代表了空语句。这两条语句的作用是在poll()函数为真()之前一直等待。
表达式语句
表达式语句用于向变量赋值,或进行数学计算,或进行函数调用。表达式语句也是我们最常用的一种语句,语法格式为:
表达式;
下面几行程序都是合法的表达式语句:
str=\"Hey\"+yourName;
val3=prevVal+4
counter++;
myValue1=counter,myValue2=val3
alert(\"Watch out!\");
retVal=16*Lang.max(val3,counter);
块语句
块语句使用两个花括号({ })包含一个语句集,形成一个语句体。WML Script的许多语句都需要使用块语句来实现语句体,快语句的语法格式为:
{
语句列表;
}
下面的简单程序就是使用块语句的例子:
}
vari=0;
var x=Lang.abs(b);
popUp(\"Remember!\");
}
变量语句
变量语句用于生命变量并可进行变量的初始化赋值。如果用户不赋值,那么WML Script会自动将变量语句生命的变量赋予一个空字符串(\"\")。基本的语法格式为:
var 变量名;
如果像一次生命多个变量,则相邻变量名之间使用逗号(,)间隔,其语法格式为:
VAR 变量名1,变量名2......,变量名n;
如果想在生命变量时同时初始化变量,则可按如下语法格式书写:
var 变量名=初始化
为便于大家更好的掌握变量语句,我们给出一个多出使用该语句的程序:
function count(stu){
var result=0; //声明变量的同时初始化变量
while(str!=\"\"){
var ind=0; //每次循环都初始化一次
// 为退出循环,本块语句内应当提供修改变量str值的语句
};
return result
};
function example(param){
var a=0;
if(param>a){
var b=a+1; //声明b变量的同时使用a变量初始化b变量
}else{
var b=a+2; //声明c变量的同时使用a变量初始化c变量
};
return a; //返回a变量的值
};
注释语句
严格来讲,注释语句在WML Script中还不算是真正的语句,它只是一种前指向的规定。不过它也有严格的语法和标注方法,所以我们这里还是像其他编程语言处理的一样,把WML Script注释方法以语句的形式介绍一下。
注释在程序执行的时候没有任何作用,但是可以用于对程序进行解释,则增强程序的可读性。为了形成良好的编程风格,我们应该养成书写注释的良好习惯,注释有两种表达方式:
(1)通过双斜线注释一行,这样在双斜先后的字符将成为注释而不被执行。该注释行可以单独一行书写,也可以放在其他语句的后面。
例如,可以进行如下所示的注释:
//变量j用于小数每月的天数
j=0; //我们这里将j赋值为0
(2)通过符号“/*”和“*/”来规定注释语句,这种注释方式可以进行多行注释,符号“/*”和“*/”之间的内容就是注释语句。例如,可以进行如下所示的多行注释:
/*我们定义了两个变量:i和j。其中:
i用于描述每年中的月数,
而j用于描述每月的天数*/
j=0; /*我们这里将j赋值为0*/
return语句
return语句主要用在函数体中,在函数结束前,可以通过return语句,把函数处理的结果返回给调用函数的语句。它的语法格式如下:
return表达式;
下面的函数给出了应用return语句的例子:
function square(x){
if(!(Lang.isFloat(x)))return invalid;
return x*x
};
5.1.2 条件语句
在条件语句中,当满足某种条件时 ,就会执行指定的一些代码,而在代码组另外某种条件时,则会执行另外一些代码。WML Script的条件语句就是if...else语句,它的一般表达相识如下:
if(条件){
代码块1
}
else{
代码块2
}
这样,当条件满足时,就执行代码块1;如果条件不满足则执行代码块2。代码块和代码块2中如果只有一个条语句,那么,花括号({ })就可以省略;而如果有多条语句,则必须实用花括号将代码块包括在其中。在if...else语句种,其中的else部分是可选的,也就是说,我们可以使用如下的表达形式:
if(条件){
代码块
}
这样,当条件满足时,就执行代码块,如果条件不满足则什么也不做。
例如,如果我们需要对一个学生的成绩进行判定,如果大于等于60分,那么我们就认为该学生成绩合格了,反之则认为不合格,同时一并将状态记录到变量status种,相应的WMLScript语句如下所示:
if(score>=60) status=\"pass\";
else status=\"fail\";
再如,我们可以通过对天气是否阳光普照(sunShines)的情况进行判断,来给变量myDay赋值,并累计好天气(goodDays)的天数。程序如下:
if(sunShines) {
myDay=\"Good\";
goodDays++;
}else
myDays=\"Oh well...\";
5.1.3 循环语句
使用循环语句可以反复执行某个代码块,直到循环结束条件满足后才停止执行。WML Script中有两种循环语句:for语句和while语句,同时还有两终于循环密切相关的操作语言:break语句和continue语句。
for语句
for语句可以创建一个带条件的循环,它还有3个可选的条件表达式,用于控制循环。这3个条件表达式放在一个括号里,并以分号(;)间隔。for语句的一般语法形式如下:
for(初始表达式;循环条件;递增表达式){
代码块
}
for语句的执行主要包括以下几个步骤:
(1)执行初始表达式。在一般情况下,初始表达式完成的功能是在循环中对循环计数器赋初值。所以在这种意义上,初始表达式也可以采用“var 变量声明列表;”的形式来定义。
(2)判断循环条件。如果循环条件为真(ture),则执行循环体中的语句,即至步骤(3);否则,循环条件为假(false)或者invalid,就结束循环;
(3)执行循环代码。然后,在执行递增表达式。一般情况下,我们在递增表达式中对循环计数器进行处理,最后在返回步骤2执行。
例如,下面的for语句建立了一个循环。初始表达式为定义变量index并付初值0,循环条件为index<100,递增表达式为每循环一次index增加1。当index增加到100时候,循环结束。程序如下:
for(var index=0;index<100;index++){
count+=index;
myFunc(count);
};
while 语句
while语句也可常见一个循环,它的一般语法表达式如下:
while(循环条件){
代码块
}
while语句的执行过程包括以下几个步骤:
(1)判断循环条件是否为真。如果循环条件为真,则执行循环;如果为假或为invalid,则跳出循环。
(2)执行循环中的代码块,然后返回步骤(1)
下面的程序就是使用while语句的简单例子:
var counter=0
var total=0
while(counter<3){
counter++;
total+=c;
};
其中建立的循环仅当变量counter的值小于3时执行,否则就结束循环。
显然,如果循环条件不能为假或为invalid,那么while循环就会无休止的反复执行下去。因此,我们在代码块中一定要有能够改变循环条件的变量,否则,就很有可能会陷入死循环而不能终止程序,下面就是一个死循环的例子:
var x=1;
var y=0;
while(x<=1){
y=x+1;
}
这个程序中,因为变量x的值在循环中不能发生变化,所以循环条件在判断的时候永远为真,所以成为了死循环。因此,对于while语句我们往往使用如下所示的语法形式:
初始表达式
while(循环条件){
代码块
递增表达式
}
这种情况下,while语句的功能和for语句的功能就一样了,不过用while语句编写的程序可读性更强一些。所以我们也可以采用while语句来完成index增加到100的循环。
程序如下:
var index=0
while (index<100){
counter+=index;
myFunc(count);
index++;
};
break语句
为了更好的解决死循环问题,WML Script项大多数编成语言一样提供了break语句。break语句可以使程序执行跳出循环。不论是for语句还是while语句,只要在循环中使用了break语句,那么程序执行到break语句后就立即跳出当前循环,然后继续执行下去。
break语句的予发行时如下:
break;
例如,在下面的函数中我们使用了break语句,它是当index=3时跳出循环。如果不是用该语句,函数中的while循环直到index=6时才可以结束。程序如下:
funcition testBreak(x){
var index=0;
while(index<6){
if(index==3)break;
index++
};
retrun index*x;
;
continue语句
continue语句的功能和break语句的功能看起来有些类似,但实际上却不一样。循环执行时遇到break语句通常是跳出当前循环,但循环执行到continue语句并不跳出当前循环,而是不执行循环中在continue语句后面的代码块,直接结束循环的本轮运行,然后马上开始下一轮循环的运行。
在while语句的循环中,遇到continue语句后,程序会直接判断循环条件从而开始下一轮循环。在for语句的循环中,遇到continue语句后程序会直接执行递增表达式,然后判断循环条件从而开始下一轮循环。
例如,我们想利用for循环求1到10之间偶数的和,其WML Script语句如下:
var sum=0;
for (var j=1;j<=10;j++){
if(j%2!=0)
continue;
sun+j;
};
在这个例子中,在j%2!=0的情况下,也就是j为奇数的情况下,程序执行continue语句,这时,并没有如同break语句一样跳出循环的运行,而是不执行循环中后面的语句而直接执行递增表达式开始下一轮循环的执行,这样,就可以不将其数j的之类即如总和中。
再如,我们想利用while循环求0到4之间出3以外几个数的和,则可以使用continue语句进行控制。程序如下;
var index=0;
var count=0;
while (index<5){
index++;
if(index==3)
continue;
cont+=index;
};
这以程序中,当index等于3时,“index==3”为真,所以执行continue语句,不再把此时index的值加大count中,而是开始下一轮的循环。
5.2 函数的声明与调用
在WML Script中,函数是一种能够完成某种功能的代码块,并可以在脚本中被事件处理或被其他语句调用,也可以被WML程序所处理和调用。一般地,当我们编写WML Script脚本时,如果脚本中的代码长度还是很长,则一般还可以根据功能将函数再进行划分,分成为几个功能更加单一的函数。虽然说这样对长代码的处理方法并不是编写脚本程序的强制性要求,但通过函数的划分和运用,我们可以使得WML Script脚本具有更好的可读性,也便于我们对脚本程序的编写与调试。而且,如果在某些脚本中有多处完全相同的代码块,那么我们也可以将这些代码快些为一个函数,然后在脚本中调用这个函数,从而提高代码的重要性,简化代码的编写工作。
WML Script的函数共用和Jave语言、C/C++语言的函数有所不同。我们知道,Jave语言、C/C++语言中有函数和过程之分,函数能够完成一定的功能并有返回值,而过程进可完成一定的功能但没有返回值。可是,WML Script中并不区分函数和过程,因为它只有函数,没有过程。WML Script的函数完成一定功能后始终有返回值,不过返回值分两种情况,即非空的返回值和空字符串(\"\")形式的返回值。前者是真正的返回值,后者其实相当于没有返回值。也就是说,WML Script中的函数同时具有其他语言中的函数和过程的功能。
5.2.1 函数的声明
使用函数时,要根据函数的调用使用,而调用函数前必须声明函数,也就是需要先定义函数。WML Script中定义函数的一般方式如下:
function函数名(参数列表)
{
代码块
};
另外,WML Script规定使用extern关键字来声明一个外部函数:
extern function函数名(参数列表)
{
代码块
};
从中可以看出,函数的定义有以下3部分组成:
(1)函数名。即函数的名称,其命名规则应遵守WML Script的标识规则。调用函数时都是通过函数名进行调用的,所以函数必须要有函数名。
函数命名时,一般要使用能够描述函数功能的但此来作为函数名,也可以使用多个单词组合进行命名,这样做的好处是能够提高WML Script脚本的可读性。
函数名在同一个WML Script脚本文件里必须是唯一的。如若不然,则会导致函数定义混乱。
(2)参数列表。即调用函数时需要的参数。参数列表通常是可选的,有的函数需要,有的函数可能不需要。参数列表的作用是向函数传递一些参数,使得函数可以直接使用这些参数的值。
调用函数的时候,参数个数和类型必须和函数定义示所声明的参数个数即类型保持一致。而且函数的参数就如同似函数体内的局部变量,它们在函数调用的时候被初始化。
(3)代码块。它是函数的主体部分。代码块中的代码包含在以对花括号({ })中,代码块可以执行并完成函数的功能。编写代码块是应当遵循WML Script的编程规则。
有时,函数需要返回一个值给调用函数的语句,则应该在代码块的后面一行使用return语句,返回所需的数值。
与C/C++等语言类似,WML Script的函数是可以嵌套的,以就是说,在一个函数中还可以调用其他函数。但是,函数声明是不能嵌套,这是WML Script的强制性规定。
下面几行语句就是定义函数的简单例子:
function currencyConverter(currency,exchangeRate)
{
return currency*exchangeRate;
};
其中,该函数的名称为currencyConverter,参数有currency和exchangeRate两个,函数代码块包含一条语句,用于返回currency和exchangeRate的乘积。
下面是一个使用extern定义外部函数的例子。其中函数名为textIt,它没有参数,函数体中定义了两个赋值变量,一个赋整数,一个赋函数值:
extern function testIt(){
var USD=10;
var FIM =currencyConverter(USD,5.3)
};
5.2.2 函数的调用
编写好的函数必须经过合法的调用,才可以发挥它应用的作用。函数调用将返回一个值,比如一个计算结果。WML Script中的函数主要可以分为内部函数、外部函数和库函数,下面我们就介绍这3类函数的调用方法。
内部函数
所谓内部函数是指函数的定义与其调用函数在同一个脚本文件内的函数,对内部函数的调用称为内部调用。内部函数的调用非常简单,只需提供函数名和所需参数值即可,参数值必须和函数定义时指定的参数个数即类型一致。而且函数调用需要使用操作符来接收或处理被调用的返回值。
内部函数可以在其定义之前调用,也可以在其定义之后调用。例如,下面就是一个在函数定义之后调用的例子。
function test1(val){
return val*val;
};
function test2(param){
return test1(param+1);
};
这个例子中定义了两个函数test1和test2。test1函数用于计算给定参数值的平方并将结果返回;test2函数将给定的参数值加1,然后这个和为参数值,来调用test1函数,得到结果后在将给结果返回到调用test2函数的语句。
注意,本例中test2函数调用了test1函数,这种在函数中调用其他函数的方法称为函数调用嵌套。WML Script的内部函数、外部函数和库函数都支持嵌套调用,后面我们专门介绍这方面的内容。
外部函数
外部函数使一个在WML Scrupt外部文件中定义的函数。调用外部函数的方法与调用内部函数的方法基本类似,不同之处在于调用处外部函数时一是要指定外部文件的地址即名称,二是要在调用的外部函数名的前面加上外部文件的名称。
WML Script规则使用use url来指定外部文件,语法格式为:
use url还有外部函数的外部文件名 外部文件所在的URL;
这样,WML Script的预编译头就可以将外部文件映射为一个可以在内部使用的标识。然后,使用这个标识并加上井号键(#)和标准的函数调用即可实现外部函数调用,语法格式为:
外部文件名#外部函数(参数列表);
例如,http://www.host.com/script下有我们需要的外部文件,名为OtherScript,所以我们可使用use url来指定该文件:
use url OtherScript\"http://www.host.com/script\"
这一外部文件中含有我们需要调用的外部函数testme,则可采用“外部文件名#外部函数(参数列表)”的形式来调用它:
OtherScript#testme(param+1);
这个例子完整的写出来,就是下面的程序:
use url OtherScript\"http://www.host.com/script\"
function test(param){
return OtherScript#testme(param+1);
};
库函数
特别指定,WML Script的库函数一律是指它的标准库函数。因为与标准库函数对应,WML Script还有一些非标准的库函数。我们这里先介绍标准库函数,非标准库函数后面再介绍。
所有库函数都有所数的库,函数的库中通常含有一类函数。因此,调用某个库函数时,一要指定它的库名,二要指定它的函数名。WML Script规定,调用标准库函数时可以通过在函数库的名字后面加上句点号(.)和库函数的标准调用来实现,语法格式为:
函数库名.函数名(参数列表);
例如,WML Script的浮点库即Float库中有一个开根方的函数sqrt,该函数只有一个参数,那么调用squrt库函数的方法为:
Float.sqrt(number);//这里要求number大于或等于0
下面给出了调用库函数的简单例子。首先一param参数值调用Lang.abs()函数,返回结果加1后再作为参数调用Float.sqrt()函数,它的返回结果作为内部函数test的返回值:
function test(param){
return Float.sqrt(Lang.abs(param)+1);
};
2.3 函数的嵌套调用
WML Script的函数定义都是互相平行、独立的,定义函数的时候我们不能在一个函数内定义另外一个函数,也就是说,函数定义是不能嵌套的。但是,函数调用确是可以嵌套的,也就是说,我们可以在调用一个函数的过程中调用另外一个函数。
它的执行过程是:
(1)执行a函数开头部分;
(2)遇到调用b函数的操作语句,流程则专区执行b函数;
(3)执行b函数开头部分;
(4)遇到调用c函数的操作语句,流程则专区执行c函数;
(5)执行b函数,如果没有其他嵌套的函数,则完成c函数的全部操作;
(6)返回调用c函数的语句,即返回到b函数;
(7)继续执行b函数中尚未执行的操作,直到b函数结束;
(8)返回a函数中调用b函数的语句;
(9)继续执行a函数的剩余操作,直到函数结束。
function myFunC(param1){
return param1*param1=Float.squt(Lang.abs(param)+1);
};
function myFunB(param0){
return myFunC(param0+1)*|param0+12;
};
function myFunA(param){
return myFunB(param*param+1);
};
5.3 预编译
WML Script的预编译主要用于在编译阶段控制编译器的行为。与编译头一般在文件开头和函数声明之前指定,WML Script规定所有的预编译头都是一关键词use加上指定的预编译属性进行指定。
在大多数的编程中,我们比较长用的预编译行为主要涉及外部文件声明、访问权和Meta信息设置。
5.3.1 外部文件
我们知道,使用URL地址可以定位一个WML Script文件。利用该URL地址;在WML Script编程中我们可以通过预编译来调用WML Script的外部文件,外部文件预编译头的声明方法是use url,其语法格式如下:
use url外部文件名 \"URL\"地址
这样,我们在当前文件的编程中就可以使用该预编译头声明的外部文件,从而可以调用该外部文件的函数。其语法格式为:
外部文件名#函数名(参数列表);
例如,我们希望在当前的WML Script程序中调用OtherScript外部文件中的check()函数,而且我们知道OtherScript文件的URL地址为http://www.host.com/app/script。因此,我们可以使用use url来声明这一外部文件:
use url OtherScript\"http://www.host.com/script\"
随后,我们就可以在程序中调用OtherScript中的check()函数了:
function test(par1,par2)
{
return OtherScript#check(par1,parr2);
};
其中调用执行的过程如下:
(1)找到WML Script外部文件的URL地址;
(2)当前函数从指定的URL地址值装载外部文件;
(3)检测外部文件的内容,并执行其中的check()函数。
ure url 预编译头指定的外部文件名在当前程序中必须唯一,用户不能指定不同URL地址的同名外部文件,否则在调用外部文件时就会发生混乱。
另外,use url预编译头中的URL地址也可以是相对URL地址。相对URL的起始位置是当前程序文件所在的位置,并在此基础上根据URL进行定位。
如果URL地址中的字符包含有转义字符,则WML Script将根据转义要求进行转义。不过,程序在编译的时候编译器并不会对他们进行转义,而是在程序执行时完成,检查URL格式和URL地址的有效性。
5.3.2 访问权限
我们可以使用访问权限预编译设保护文件的内容,实现访问控制。WML Script编程中,必须在调用外部函数之前使用访问权限预编译头声明外部文件的访问权限。不过,WML Script访问权限检查的缺省值是不进行检查,即disabled.但访问权限一经声明,以后当调用外部函数的时候,编译器就会检查外部文件的访问权限,以决定调用这是否有权使用该文件及其内含函数。
访问权限预编译头的声明方法是use access,其语法格式如下:
use access domain操作域名 path操作路径:
访问权限预编译头通过指定domain和path属性来决定编译器将要进行什么样的检查工作。如果文件有domain或者path属性,那么文件所在的URL就必须和属性中的值一致。比较时,域和路径都依据URL大写规则进行比较。具体的比较预则如下:
(1)操作域与URL中的域后缀相匹配。与后缀匹配是值所有的子域从后向前都必须一致。例如:www.wapforum.org和wapforum.org相匹配,而与forum.org并不匹配。
(2)操作路径和URL中的路径前缀相匹配。路径前缀匹配是值从前向后必须一致。例如:“/X/Y”与“/X”相匹配,而不是和“/XZ”相匹配。
(3)却省的domain数行为当前的文件域,就是“/”。
不过,为了简化编程,有时WMLScript并不需要直到外部文件的绝对路径,我们只需提供文件的相对URL即可,用户浏览器执行程序是卡相对路径自动转换为绝对路径,根据路径属性进行匹配。例如:如果访问权限预编译头及其指定属性为:
use access domain\"wapforum.org\"path\"/finance\";
则可以使用以下的路径来调用指定文件中的外部函数,它们都符合相对URL地址匹配规则:
http://wapforum.org/finance/money.cgi
http://www. wapforum.org/finance/money.cgi
http://www. wapforum.org/finance/demos/packages.cgi?x+123&y+456
而以下的路径调用则非法的,因为它们或者操作域不对,或者URL地址不能与指定的相对URL相匹配:
heep//www.test.net/finance
http//www.qapforum.org/internal/foo.wml
需要强调指出的是,WML Script规定,同一程序中只能定义一个访问权限与编译头,否则就会导致编译错误。
5.3.3 Meta 信息
我们还可以通过与编译头的形式声明WML Script文件的Meta信息。Meta信息主要用于指定文件所需Mete属性的属性名(Property name)、属性值(Content)以及文件的配置(信息),属性都属于字符串类型的数据。Mate信息域编译头使用use meta声明,其语法格式为:
usr meta 属性 该属性Meta信息:
Meta的属性主要包括Name、HTTP Equiv和User Agent三种,下面我们分别讲解它们的声明方法:
(1)Name。该属性用于指定服务器使用的Meta信息。这些信息仅供服务使用,用户浏览器并不理会这些信息。
例如,以下Name属性的Meta信息指定了服务器的创建时间:
use meta name \"Created\"\"26-June-2000\";
该信息只会作用于服务器,而不会影响用户浏览器的操作。
(2)HTTP Equiv。该属性用于指定需要解释为HTTP头的Meta信息。对于已经编译的文件来说,当它到达用户浏览器前,WML Script将根据HTTP Equiv属性指定的Meta信息将文件转换为WSP或HTTP的响应头,进行文件的解释和执行。
例如,以下声明的http equiv属性指定按照脚本语言的关键字来解释当前文件:
use meta http equiv\"Keywords\"\"Script,Language\";
(3)User Agent。该属性用于定义用户浏览器使用的数据类型。例如:
use meta user agent\"Type\"\"Test\";
它指定当前数据必须立即发送给用户浏览器,然后马上清除掉。
5.4 执行时的错误检测与处理
WML Script函数的功能提供用户服务,并希望用户界面能在任何的状况下运作顺利,因此错误的处理是最大的课题,这表示了语言可能不提供预期的机制,如他应该可以防止错误发生或提醒用户注意并采取适当的动作,种植储蓄执行是最后的手段。下面几个小节列出了当为码下载并执行时会发生的错误,一些程序上的错误并不在谈论的范围(如无穷循环),像这类的例子就需要手动来终止。
5.4.1 错误检测
错误检测工具能让你检测错误但会干扰系统的动作,因为WML Script是弱格式语言,所以由一些特殊功能的工具来检测有invalid数据格式所引起的错误:
检测给定的变量包含的是正确值:WML Scritp含有格式确认函数库程序如:Lang.isInt()Lang.isFloat()、Lang.parseInt()、Lang.parseFloat。
检测给定的变量包含的只是正确的格式:WMLScript含有运算符typeof与isvalid能让你使用。
5.4.2错误处理
错误处理是在发生错误之后,有些状况是错误检测无法防止的,如内存限制后外部信号等,或者是数据很难处理,如溢出(overflow)或亏失(underflow),而这些状况可以分为两类:
严重错误(fatalerror):这种错误会造成程序终止,因为WML Scritp程序会让一些用户界面调用,程序终止通常会跟调用它的用户界面发出信号,用户界面就会告知用户这个错误。
错误(non-fatalerrow):这种错误会把信号传回程序,如一些特殊的值,然后由程序决定所要采取的行动。
下列的错误是根据他们的严重性来区分。
5.4.3 严重错误(fatalerror)
下面的小节会讨论WML Script的严重错误。
位码错误(bytedode error)
这些错误跟位码与由WML Script位码解译器所执行的指令有关他们指出了错误的元素群、无效的指令、指令所使用的参数无效,或指令无法执行。
验证错误(verification failed)
说明:调用的程序中的特定位码无法通过验证。
如何发生:每次程序试着用外部程序。
范例:var a = 3*OtherScript#doThis(param)
严重性:严重。
判定状况:当检测位码验证式。
解决方法:终止程序与WML Script解译其调用者的错误信号。
说明:调用一个函数库程序时发生严重错误。
如何发生:每次调用函数库程序。
范例:var a = string.format(param)
严重性:严重。
判定状况:无
解决方法:终止程序与WML Script解译其调用者的错误信号。
说明:调用函数参数的数目跟被调用函数的参数数目不符合。
如何发生:调用外部程序。
范例:编译器参生一个无效的参数给予指令使用,或者被调用的程序参数数目改变了。
严重性:严重。
判定状况:无
严重性:严重。
解决方案:终止程序与WML Script解译器调用着的错误信号。
说明: 在特定的程序中找不到所需要的外部程序。
如何发生:调用外部程序。
范例: var a =3*OtherScript#doThis(param)
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。
说明: 由于在网络服务器的程序存取又无法修复的错误或特定程序并不在网络服务器中所引起的程序无法载入。
如何发生:调用外部程序。
范例: var a =3*OtherScript#doThis(param)
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。
说明: 存取错误,所调用的外部程序加了保护。
如何发生:调用外部程序
范例:var a =3*OtherScript#doThis(param)
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。
说明: 因为程序错误造成stack underflow。
如何发生:程序要取出(pop)一个空堆
范例: 当组译器产生错误码。
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。
说明:执行调用Lang.abort() 是发生的错误。
如何发生:每当程序调用Lang.abort()函数。
范例: Lang.abort(\"unrecoverable error\")
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。
说明:发生堆栈溢出。
如何发生:程序资源太多或要推入太多的变量到运算之中。
范例: function f|(x)(f(x+1););
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。
说明:没有多余的内存可供解译器使用。
如何发生:作业系统无法配置多余的空间给解译器适使用。
范例: function f(x){
x=x+\"abcdefghijklmnopqrstuvxyz\";
f(x) ;
};
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。
说明:用户终止程序的执行(如按下reset钮)
如何发生:随时。
范例: 当应用程序正在执行是用户按下reset钮。
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。
说明:当程序执行中,发生了外部严重的错误。
如何发生:随时。
范例: 电力微弱,系统自动。
严重性:严重。
判定状况:无
解决方案:终止程序与WML Script解译器调用着的错误信号。
5.4.4 一般错误(Nonfatal error)
下面说明了WML Script的一般错误:
计算错误(computational error)
这些错误是由于WML Script数学上的运算所造成。
除以零(divide by zero)
说明:发生了除以零的状况
如何发生:当程序中有除以零的状况。
范例:var a= 10;
var b= 0;
var x= a/b;
var y= a div b;
var z= a%b;
a/=b;
严重性: 一般。
判定状况:高
解决方案:产生结果为invalid。
说明:发生了除以零的状况
如何发生:程序要执行浮点数运算。
范例:var a = Float.precision();
var b = Float.precision();
var c = a* b
严重性:一般。
判定状况:高,在某些状况很困难。
解决方法:产生的结果为浮点数值0.0
常数参考错误(constant reference error)
说明:所参考的浮点数实字为not a number。
如何发生:程序试着存取一个浮点数实字但组译器产生了not a number的浮点数常数。
范例:参考浮点数常数。
严重性:一般。
判定状况:高
解决方法:这会产生invalid值。
说明:参考的浮点数实字不是正无穷大就是负无穷大的浮点数常数。
如何发生:程序试着存取一个浮点数实字但组译器产生了正无穷大或负无穷大的浮点数常数。
范例:参考浮点数常数。
严重性:一般。
判定状况:高
解决方法:这会产生invalid值。
说明:需要参照浮点数值所发生的错误。
如何发生:程序需要使用浮点数值但环境值支持整数值。
范例:var a = 3.14;
严重性:一般
判定状况:高
解决方法:这会产生invalid值。
转换错误
这个错误的发生同WML Script所支持的自动转换有关。
说明:欲转换成整数值,但这个值超过整数所能接受的范围(正或负)。
如何发生:程序试着自动转换成整数时。
范例: var a = -\"99999999999999999999999999999999999999999\";
严重性:一般
判定状况:高
解决方法:这会产生invalid值。
说明:欲转换成浮点数,但这个值小于浮点数所能接受的范围(正或负)。
如何发生:程序时值自动转换成浮点数时。
范例:var a = -\"99999999999999999999999999999999999999999\";
严重性:一般
判定状况:高
解决方法:这会产生invalid值。
说明:欲转换成浮点数,但这个值小于浮点数所能接受的范围(正或负)。
如何发生:程序时值自动转换成浮点数时。
范例:var a = -\"99999999999999999999999999999999999999999\";
严重性:一般
判定状况:高
解决方法:这会产生浮点数0.0。
6.5 URL函数库
名称:URL
说明:这个函数库包含了处理绝对的URL与相对URL的程序,一般的URL语法如下:://:/;?#
isValid
程序:isValid(url)
说明:如果给予的url值是正确的URL语法,则回传ture,否则回传false
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:布尔值或invalid
例外状况:无
范例:var a=URL.isValid
(\"http://www.acme.com/script#func()\"); //a=ture
var b=URL.isValid(\"../common#test()\"); //b=ture
var c=URL.isValid
(\"experimental?://www.acme.com/pub\"); //c=false
getScheme
程序:getScheme(url)
说明:回传给予url的调用方式scheme
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.geScheme(\"http://w.a.com\"); //a=\"http\"
var b=URL.getSceme(\"w.a.com\"); //b=\"\"
getHost
程序:getHost(url)
说明:回传给予url的主机
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.geHost(\"http://www.acom.com/pub\"); //a=\"www.acm.com\"
var b=URL.getHost(\"path#fray\"); //b=\"\"
getPort
程序:getPort(url)
说明:回传给予url的端口(port)
如果port没有制定,则回传空字符串
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.getPort(\"http://www.acom.80/path\"); //a=\"80\"
var b=URL.getPort(\"http://www.acom./path\"); //b=\"\"
getPath
程序:getPath(url)
说明:回传给予url的路径(path)
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.getPath(\"http://w.a.com/home/sub/comp#frag\"); //a=\"/home/sub/comp\"
var b=URL.getPath(\"../home/sub/comp#frag\"); //b=\"../home/sub/comp\"
getParameters
程序:getParameters(url)
说明:回传给予url的路径(parameter)
如果没有指定参数,则回传空字符串
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.getParameters(\"http://w.a.c/scr;3;2?x=1&y=3\"); //a=\"3;2\"
var b=URL.getParameters(\"../scr3;2?x=1&y=3\"); //b=\"../home/sub/comp\"
getQuery
程序:getQuery(url)
说明:回传给予url的询问部分(query)
如果没有指定的询问部分,则回传空字符串
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.getParameters(\"http://w.a.c/scr;3;2?x=1&y=3\"); //a=\"3;2\"
getFragment
程序:getFragment(url)
说明:回传给予url的片断(fragment)
如果没有指定片断,则回传空字符串
绝对与相关URL都能支持
相关URL不会被转成绝对URL
参数:url=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.getFragment(\"http://www.acom.com/cont#fray\"); //a=\"fray\"
getBase
程序:getBase()
说明:回传次WML Script程序的绝对URL(没有fragment的部分)。
参数:无
回传值:字符串
例外状况:无
范例:var a=URL.getBase(); //Result;
\"http://www.acme.com/test.scr\"
getReferer
程序:getReferer()
说明:回传调用目前程序资源的最小相关URL(与目前程序的基本URL的相关)
内部程序调用并不会改变参照者
如果目前的程序并没有参照者,则回传空字符串
参数:无
回传值:字符串
例外状况:无
范例:var base=URL.getBase(); //base
=\"http://www.acme.com/current.scr\"
var prferer=URL.getReferer(); //referer=\"app.wml\"
resolve
程序:resolve(baseUrl,embeddedUrl)
说明:根据RFC2396的文件,由给予的基本base与插入embeddedUrl回传绝对URL
参数:baseUrl=字符串
embeddedUrl=字符串
回传值:字符串或invalid
例外状况:如果遇到不正确的URL语法,则回传invalid
范例:var a=URL.resolve(http://www.foo.com/,\"foo.vcf\"); //a=\"http://www.foo.com/foo.vcf\"
escapeString
程序:escapeString(string)
说明:这个程序会将所给与string字符串之中的特殊字符使用十六进制逃脱序列来替代(你必须使用量为逃脱序列格式%xx),这些逃脱字符如下:
控制字符(control characters):US-ASCII编码的字符00-1F与7F
空格(Space):US-ASCII码编字符20十六进制
保留字(Reserved):\";\"|\"/\"|\"?\"|\":\"|\"@\"|\"=\"|\"+\"|\"$\"|\",\"
Unwise:\"{\"|\"}\"|\"|\"|\"\\\"|\"\"|\"[\"|\"]\"|\"`\"
Delimes:\"<\"|\">\"|\"#\"|\"%\"|\"<>\"
给予的字符串如果已经是使用逃脱自负,则不会执行URL解析
参数:string=字符串
回传值:字符串或invalid
例外状况:如果字符串string含有非US-ASCII的字符,则回传invalid
范例:var a=URL.escapeString
(\"http://w.a.c/dck?x=u007ef#crd\");
// a=\"http%3a2f%2fw.a.c%2fdck%3fx%3def%23crd\"
unescapeString
程序:unescapeString(string)
说明:这个程序会将所给与string字符串之中每个可能是由URL.escapeString() 程序所产生的逃脱序列使用它所代表的字符加以替代。
参数:string=字符串
回传值:字符串或invalid
例外状况:如果字符串string含有非US-ASCII的字符,则回传invalid
范例:var a=\"http%3a2f%2fw.a.c%2fdck%3fx%3def%23crd\";
var b=URL.unescapeString(a); //b
=\"http://w.a.c/dck?x=12#crd\"
loadString
程序:loadString(url,contentType)
说明:回传有所给予的绝对URL与contenttype所指出的内容。
如果内容格是不是下列法则所规范的话,则是错误的:
你只能界定一种内容格式,整个字符串必须和一种内容格式相符,而 且你不能有额外的前或后空格。
格式必须是正文,但次格式没有限制,格式的开头一定是\"text/\"。
这个程序的动作如下:
文件的内容会载入使用给予的contentType与url,其他所需的数形式有使用用户界面的预设面。
如果载入成功而且回传的内为格式与所给予的contentType相符,则内文会被转换成字符串再回传。
如果载入成功或回传的内文格式不正确的话,则会回传特定的错误码。
参数:url=字符串
contentYype=字符串
回传值:字符串、整数或invalid
例外状况:如果载入失败其回传的错误码和所使用的URL Scheme有关
如果使用HTTP或WSP架构,会回传HTTP错误码。
如果给予的contentType错误的话,则会回传invalid
范例:var a=\"http%3a2f%2fw.a.c%2fdck%3fx%3def%23crd\";
var b=URL.unescapeString(a); //b
=\"http://w.a.c/dck?x=12#crd\"
loadString
程序:loadString(url,contentType)
说明:回传有所给予的绝对URL与contenttype所指出的内容。
如果内容格是不是下列法则所规范的话,则是错误的:
你只能界定一种内容格式,整个字符串必须和一种内容格式相符,而 且你不能有额外的前或后空格。
格式必须是正文,但次格式没有限制,格式的开头一定是\"text/\"。
这个程序的动作如下:
文件的内容会载入使用给予的contentType与url,其他内文所需的数形式有使用用户界面的预设面。
如果载入成功而且回传的内容为格式与所给予的contentType相符,则内文会被转换成字符串再回传。
如果载入成功或回传的内文格式不正确的话,则会回传特定的错误码。
参数:url=字符串
contentYype=字符串
回传值:字符串、整数或invalid
例外状况:如果载入失败其回传的错误码和所使用的URL Scheme有关
如果使用HTTP或WSP架构,会回传HTTP错误码。
如果给予的contentType错误的话,则会回传invalid
范例:var myUrl=\"http://www.acme.com/vcards/myaddr.vcf\";
myCard=URL.loadString(myUrl,\"text/x-vcard\");
6.6 WML浏览器函数库
名称:WML Brower
说明:这个函数库所包含的程序是让WML Script用来存取与WML相关的内文,这些程序不能有任何的副作用,并在下列的状况下回传invalid值。
系统不支持WML浏览器。
WML浏览器无法使用WML Script解译器。
getVar
程序:getVar(name)
说明:回传目前浏览器内文的所给予名称name的变量值。
如果所指定的变量不存在,回传一个空字符串。
变量名称必须依照WML语法来使用。
参数:name=字符串
回传值:字符串或invalid
例外状况:如果变量名称不合语法,则回传invalid
范例:var a=WMLBrowser.getVar(\"name\");
// a\"Jon\"或者变量的值
setVar
程序:setVar(name,value)
说明:在目前的浏览器之中,如果所给予名称name的变量,它的值同给予的值value设定的一样的话,回传ture,否则回传false。
变量名称必须依照WML语法来使用。
变量值必须是合法的XML CD ATA
参数:name=字符串
value=字符串
回传值:布尔值或invalid
例外状况:如果变量名称或它的值不合语法,则回传invalid
范例:var a=WMLBrowser.setVar(\"name\",Mary); // a=true
go
程序:go(url)
说明:将给予的url所标记的内文载入,这个程序予WML的GO动作意思相同。
如果所给予的url字空字符串(\"\"),则不会载入任何内文。
go()与prev()函数库程序会互相推翻,在回传控制与WML浏览之前都可以加以调用多次。
只有最后的调用设定的会保持作用,如果最后的调用为go()或prev(),其所设定的url为空字符串(\"\"),所有的要求都会被取消。
这个程序回传空字符串。
参数:url=字符串
回传值:字符串或invalid
例外状况:无
范例:varcard=\"http://www.acme.com/loc/app.dck#start\";WMLBrowser.go(card
)
prev
程序:prev()
说明:告诉WML浏览器回到先前的WML Card,这个程序的功能与WML中的prev动作一样。
go()与prev()函数库程序会互相推翻,在回传控制与WML 浏览之前都可以加以调用多次。
只有最后的调用设定是会保持作用,如果最后的调用为go()或prew(),其所设定的url为空字符串(\"\"),所有的要求都会被取消。
这个程序回传空字符串。
参数:无
回传值:字符串或invalid
例外状况:无
范例:WMLBrowser.prev();
newContext
程序:newContext()
说明:将目前WML浏览器的内文清除并回传一个空字符串,这个程序的公用与WML的NEWCONTEXT属性一样。
参数:无
回传值:字符串或invalid
例外状况:无
范例:WMLBrowser.newContext();
getCurrentCard
程序:getCurrentCard()
说明:回传目前WML浏览器所处理card的最小相关URL,如果WML deck所包含目前程序的基本地址不同的话,则此程序会回传绝对URL。
参数:无
回传值:字符串或invalid
例外状况:如果没有目前的card,则回传invalid。
范例:var a=WMLBrowser.getCurrentCard();// a=\"deck#input\"
refresh
程序:refresh()
说明:强制WML浏览器更新它的内文并回传一个空字符串,而用户界面会加以更新以反应更新后的内容,这个程序与WML中的refresh功能一样。
参数:无
回传值:字符串或invalid
例外状况:无
范例:WMLBrowser.setVar(\"name\",\"Zorro\");
WMLBrowser.refresh();
6.7 Dialog函数库
名称:对话
说明:这个函数库包含典型的用户界面程序。
prompt
程序:prompt(message,defaultInput)
说明:显示给予的信息message与用户输入的提示符号,defaultInput参数包含了用户输入所需的初始内文,回传用户输入。
参数:message=字符串
defaultInput=字符串
回传值:字符串或invalid
例外状况:无
范例:var a=\"09-555 3456\"; var b=Dialogs.prompt(\"Phome number\";a);
confirm
程序:confirm(message,ok,cancel)
说明:显示所给予的信息message与两个选项:ok与cancel,等待用户选取其中一个,如果是ok则回传false。
参数:message=字符串
ok=字符串
cancel=字符串
回传值:布尔值invalid
例外状况:无
范例:function onAbort(){return Dialogs.confirm(\"Are you sure?\"),\"Yes\",\"No\";};
alert
程序:alert(message)
说明:显示所给予的信息message给用户,等待用户确定并回传一个空字符串。
参数:message=字符串
回传值:字符串或invalid
例外状况:无
范例:function testValue(textElement){
if (String.length(textElement)>8) {
Dialogs.alert(\"Enter name <8 chars!\");
};
};
6.8 函数库总结
函数库
函数库名称:
Lang
Float
String
URL
WML Browser
Dialogs
函数库与他们的程序:
Lang函数库
Abs
Min
Max
ParseInt
ParseFloat
IsInt
IsFloat
MaxInt
MinInt
Float
Exit
Abort
Random
Seed
CharacterSet
Float 函数库
Int
Ploor
Ceil
Pow
Round
Sqrt
MaxFloat
MinFloat
String 函数库
Length
IsEmpty
CharAt
SubString
Pind
Replace
Elements
ElementAt
RemoveAt
ReplaceAt
InsertAt
Squeeze
Frim
Compqre
ToString
format
URL 函数库
IsValid
GetScheme
GetHost
GetPort
GetPath
GetParameters
GetQuer
GetFragment
GetBase
GetReferer
Resolve
EscapeString
UnescapeString
loadString
WML Browse函数库
Get Var
SetVar
Go
Prev
NewContext
GetCurrentCard
Refresh
Dialogs函数库
Prompt
Confirm
Alert
posted on 2006-04-29 09:47
崛起的程序员 阅读(377)
评论(0) 编辑 收藏 所属分类:
载选文章