发表于:2013/9/9 17:14:41
#0楼
紫金桥软件提供了简单实用的脚本语言,在提供编程功能的同时尽量使其简单化。因此,脚本的功能不能与专业编程语言相比,但即便如此,现有的脚本语法及函数也已经能够满足绝大部分客户的需求。现在就目前脚本使用中遇到的一些特殊用法进行一些讨论。
continue 与break
我们知道,continue用于在循环语句中跳过当前步骤,继续执行循环语句。紫金桥软件没有提供该功能,但是我们可以用简单的if语句来代替。
举例如下:
//找出一个整型数组中的所有偶数
int i = 0;
int nArr[];
nArr.Add(0);
nArr.Add(1);
nArr.Add(2);
nArr.Add(3);
for i=0 to nArr.GetCount()
if nArr[i]%2==0 then
MsgBox(IntToStr(nArr[i],10));
endif
next
该示例中,我们用” nArr[i]%2==0”作为判断条件,取代了continue功能,实现起来很简单。
在C语言中break用于结束本循环的所有步骤,当计算机进程执行完break语句时,循环体中其后的所有语句将不再执行,直接挑出循环体。同样,紫金桥软件并未提供break功能。但是我们仍然有办法用其他方式取而代之。
举例如下:
//在字符串数组中查找指定字符串,返回找到的元素序号
int i = 0;
string strArr[];
int nBreak = 0;
strArr.Add("张三");
strArr.Add("李四");
strArr.Add("王五");
strArr.Add("马六");
strArr.Add("田七");
while i<strArr.GetCount() && nBreak==0 do
if "王五"==strArr[i] then
MsgBox(IntToStr(i,10));
nBreak = 1;
endif
i = i+1;
endwhile
在该示例中,我们在一个人名数组中查找“王五”所在的元素序号,并以对话框的形式弹出。我们需要从头遍历整个数组,取出元素的值与“王五”对比,当我们找到元素“王五”时,我们的目的就达到了,继续循环已经没有意义。于是,我们使用一个整型变量“nBreak”来控制循环的执行,当找到所需元素时,我们给他赋值为1,使得接下来的循序条件不再成立,于是整个循环得以顺利终止。
我们应该尽量避免执行这些无意义的语句,尤其当字符串数组很长,而且每个元素中所存储的元素又很大时,这种比较所花费的时间是十分惊人的。当然,紫金桥软件中的数组提供了现成的Find函数来解决这个问题,本示例仅以此问题来引起读者对编码的执行效率的重视。
当然,如果我们的整个函数体只是为了查找一个字符串时,我们完全可以使用retrun语句来结束当前函数体,这样循环体自然也就无法继续。但是,我们往往需要做的事情并不只是查找一个字符串,或者我们查找完字符串后还要在当前函数体内做许多其他事情,在这种情况下,直接使用retrun就不能满足我们的需要了,我们让需要使用示例中的方法,避免脚本执行时间的浪费。
滤掉数组中符合条件的多个元素
我们常常在得到一个数组后,要对其执行筛选操作。比如,期末考试后,所有人的成绩被记录在一个整型数组中,现在希望过滤掉分数少于60分的成绩。观察下面的代码:
//过滤少于60分的成绩示例a
int i = 0;
int nScoreArr[];
nScoreArr.Add(35);
nScoreArr.Add(47);
nScoreArr.Add(98);
nScoreArr.Add(58);
nScoreArr.Add(84);
for i=0 to nScoreArr.GetCount()
if nScoreArr[i]<60 then
nScoreArr.Remove(i);//删除数组元素
endif
next
#list.SetItems(nScoreArr);//使用列表框显示数组
这段脚本使用一个for循环,由前至后逐次判断每个元素的值是否小于60,如果小于60则删除该序号所指向的元素。看上去似乎没有什么问题,可执行后结果却不尽人意。
执行后的结果如下:
结果是错误的。
我们发现,成绩为47的元素并没有被删除。我们先来看看数组函数Remove(Int Index) As Bool功能说明:删除数组中指定序号的元素,操作成功后,该序号之后的元素依次向前移动一个位置,数组长度减一。例如,删除序号为3的元素后,原本序号为4的元素,其序号现在变成了3,而原本序号为5的元素,现在变成了4。
这就不难解释上例脚本中存在的问题了,for循环只能从前至后地遍历数组,在for循环的第一步,序号为0的元素因满足删除条件而被删除,原本序号为1的元素现在序号变成了0,原本序号为2的元素现在序号变成了1。for循环体继续执行到第二步,取出当前序号为1的元素继续比较,但是此时序号为1的元素已不在是删除操作前序号为1的元素,它被原来序号为2的元素替换了!而原来序号为1的元素再也没有机会被遍历到,它被跳过了!执行完这段脚本后,结果自然不是我们想要的。
要想解决这个问题,我们必须避免因数组元素被删除而导致序号的变化对下接下来的循环体执行所带来的影响。for循环语句只能从前至后地遍历数组,这种影响对它来说是致命的。但是while循环语句则不然,它的语法要求十分宽松,最重要的是它可以从后至前地遍历数组。
我们看下解决方案:
//过滤少于60分的成绩示例b
int i = 0;
int nScoreArr[];
nScoreArr.Add(35);
nScoreArr.Add(47);
nScoreArr.Add(98);
nScoreArr.Add(58);
nScoreArr.Add(84);
i = nScoreArr.GetCount()-1;
while i>=0 do
if nScoreArr[i]<60 then
nScoreArr.Remove(i);//删除数组元素
endif
i = i-1;
endwhile
#list.SetItems(nScoreArr);//使用列表框显示数组
当数组中序号为i的元素被删除后,原本序号大于i的数组序号全部自减一,但是原本序号小于i的数组序号仍保持不变。while语句使用倒序循环遍历数组,也就是以从后至前的顺序访问数组,因此,每次删除操作均不会影剩余响循环体的正确执行。
执行结果如下:
结果是正确的。
continue 与break
我们知道,continue用于在循环语句中跳过当前步骤,继续执行循环语句。紫金桥软件没有提供该功能,但是我们可以用简单的if语句来代替。
举例如下:
//找出一个整型数组中的所有偶数
int i = 0;
int nArr[];
nArr.Add(0);
nArr.Add(1);
nArr.Add(2);
nArr.Add(3);
for i=0 to nArr.GetCount()
if nArr[i]%2==0 then
MsgBox(IntToStr(nArr[i],10));
endif
next
该示例中,我们用” nArr[i]%2==0”作为判断条件,取代了continue功能,实现起来很简单。
在C语言中break用于结束本循环的所有步骤,当计算机进程执行完break语句时,循环体中其后的所有语句将不再执行,直接挑出循环体。同样,紫金桥软件并未提供break功能。但是我们仍然有办法用其他方式取而代之。
举例如下:
//在字符串数组中查找指定字符串,返回找到的元素序号
int i = 0;
string strArr[];
int nBreak = 0;
strArr.Add("张三");
strArr.Add("李四");
strArr.Add("王五");
strArr.Add("马六");
strArr.Add("田七");
while i<strArr.GetCount() && nBreak==0 do
if "王五"==strArr[i] then
MsgBox(IntToStr(i,10));
nBreak = 1;
endif
i = i+1;
endwhile
在该示例中,我们在一个人名数组中查找“王五”所在的元素序号,并以对话框的形式弹出。我们需要从头遍历整个数组,取出元素的值与“王五”对比,当我们找到元素“王五”时,我们的目的就达到了,继续循环已经没有意义。于是,我们使用一个整型变量“nBreak”来控制循环的执行,当找到所需元素时,我们给他赋值为1,使得接下来的循序条件不再成立,于是整个循环得以顺利终止。
我们应该尽量避免执行这些无意义的语句,尤其当字符串数组很长,而且每个元素中所存储的元素又很大时,这种比较所花费的时间是十分惊人的。当然,紫金桥软件中的数组提供了现成的Find函数来解决这个问题,本示例仅以此问题来引起读者对编码的执行效率的重视。
当然,如果我们的整个函数体只是为了查找一个字符串时,我们完全可以使用retrun语句来结束当前函数体,这样循环体自然也就无法继续。但是,我们往往需要做的事情并不只是查找一个字符串,或者我们查找完字符串后还要在当前函数体内做许多其他事情,在这种情况下,直接使用retrun就不能满足我们的需要了,我们让需要使用示例中的方法,避免脚本执行时间的浪费。
滤掉数组中符合条件的多个元素
我们常常在得到一个数组后,要对其执行筛选操作。比如,期末考试后,所有人的成绩被记录在一个整型数组中,现在希望过滤掉分数少于60分的成绩。观察下面的代码:
//过滤少于60分的成绩示例a
int i = 0;
int nScoreArr[];
nScoreArr.Add(35);
nScoreArr.Add(47);
nScoreArr.Add(98);
nScoreArr.Add(58);
nScoreArr.Add(84);
for i=0 to nScoreArr.GetCount()
if nScoreArr[i]<60 then
nScoreArr.Remove(i);//删除数组元素
endif
next
#list.SetItems(nScoreArr);//使用列表框显示数组
这段脚本使用一个for循环,由前至后逐次判断每个元素的值是否小于60,如果小于60则删除该序号所指向的元素。看上去似乎没有什么问题,可执行后结果却不尽人意。
执行后的结果如下:
结果是错误的。
我们发现,成绩为47的元素并没有被删除。我们先来看看数组函数Remove(Int Index) As Bool功能说明:删除数组中指定序号的元素,操作成功后,该序号之后的元素依次向前移动一个位置,数组长度减一。例如,删除序号为3的元素后,原本序号为4的元素,其序号现在变成了3,而原本序号为5的元素,现在变成了4。
这就不难解释上例脚本中存在的问题了,for循环只能从前至后地遍历数组,在for循环的第一步,序号为0的元素因满足删除条件而被删除,原本序号为1的元素现在序号变成了0,原本序号为2的元素现在序号变成了1。for循环体继续执行到第二步,取出当前序号为1的元素继续比较,但是此时序号为1的元素已不在是删除操作前序号为1的元素,它被原来序号为2的元素替换了!而原来序号为1的元素再也没有机会被遍历到,它被跳过了!执行完这段脚本后,结果自然不是我们想要的。
要想解决这个问题,我们必须避免因数组元素被删除而导致序号的变化对下接下来的循环体执行所带来的影响。for循环语句只能从前至后地遍历数组,这种影响对它来说是致命的。但是while循环语句则不然,它的语法要求十分宽松,最重要的是它可以从后至前地遍历数组。
我们看下解决方案:
//过滤少于60分的成绩示例b
int i = 0;
int nScoreArr[];
nScoreArr.Add(35);
nScoreArr.Add(47);
nScoreArr.Add(98);
nScoreArr.Add(58);
nScoreArr.Add(84);
i = nScoreArr.GetCount()-1;
while i>=0 do
if nScoreArr[i]<60 then
nScoreArr.Remove(i);//删除数组元素
endif
i = i-1;
endwhile
#list.SetItems(nScoreArr);//使用列表框显示数组
当数组中序号为i的元素被删除后,原本序号大于i的数组序号全部自减一,但是原本序号小于i的数组序号仍保持不变。while语句使用倒序循环遍历数组,也就是以从后至前的顺序访问数组,因此,每次删除操作均不会影剩余响循环体的正确执行。
执行结果如下:
结果是正确的。
打造民族品牌 铸就工控业绩