这里没有软件测试的泛泛理论,只有博主的最佳实践。 博主的研究方向为静态分析和性能测试,致力于各种测试工具的引入、评估和开发。 本博的测试文章均为作者原创,转载请务必注明出处。

小骆驼书作业四:子例程

上一篇 / 下一篇  2008-07-04 14:29:30 / 个人分类:Perl

习题一:写一支名为&total的子例程,用来返回一串数字的总和。提示:子例程不应使用任何输入/输出,它应该只处理参数并将值返回给调用者。

sub total
{
 my $result = 0;
# print "@_\n";
 foreach (@_)
 {
#  print "@_\n";
  $result +=$_;
#  print "$result \n";
 }
 $result;
}

以上我的答案,很简单,不是吗?但即便是只有四行有效可执行语句,你能看到里面有三行注释,这反映了我调试的过程,最终定位的问题就是上面的黑体加大部分,没错,就是$_,我开始写的是@_。

可能还是没有完全习惯Perl中不同的前缀的不同含义,$表示Scalar标量,@表示array数组,&表示函数调用等。体现在这个简单的程序中,刚开始接触的人更容易混淆,小骆驼书中也一直强调参数数组@_跟foreach循环中的默认变量@_之间没有任何自动产生的联系。

习题3:写一支名为&above_average的子例程,用来传入一串数字并返回所有大于平均值的数字。

虽然看起来稍微复杂,但有了习题1的经验后,这已经不是什么问题。下面是标准答案

sub total
{
 my $result = 0;
 foreach (@_)
 {
  $result +=$_;
 }
 $result;
}
sub average
{
 if(@_ == 0)
 {
  return;
 }
 my $sum = &total(@_);
 $sum / @_;
}

sub above_average
{

 my $average = &average(@_);
 my @list=();
 foreach $element (@_)
 {
  if($element > $average)
  {
   push @list,$element;
  }
 }
 @list;
}

当然这是我最终的解答。但第一次我的答案可不是这样的。我老老实实的按照题目说明,只写了一个子例程&above_average实现了题目的功能,其中包含了求总和、计算平均数、形成大于平均值的数字形成的列表三个功能。其实第一个功能“求和”前面已经实现过了,有现成的例程,但我竟然没有想起重用这个现成的例程。

这可能已经不是技术问题了,是思维模式的问题,“可重用”的思想还没有深入骨髓。所以即便是掌握了子例程编写的技术方法,在思想方面还需要再强化。

复习笔记

×在Perl中子例程不需要事先声明,直接定义即可,格式为
sub func_and_proceure { }
调用时,推荐使用&,虽然某些情况下可能并不需要这个符号

×返回值可以用return,也可以不用,所以很多Perl子例程返回值采取的是“最后执行的表达式即返回值”的原则。
但如果程序要有多个返回值,如根据不同的条件返回不同的值,则子例程中间的返回值需要用return。

×子例程定义时不需要写参数列表,在使用即被调用时要传入参数,如
 $n = &max(1..10);

×子例程实现代码中,@_(Perl中默认的另外一个变量)表示传入参数的列表,在子例程执行期间有效,@_和调用时传入的列表是“复制关系”,即对@_的修改不会影响到被调用时传入的列表。

×@_是子例程的私有变量。子例程可以将参数传给其他的子例程,而不用担心遗失自己的@_变量,如上面的习题3的答案。即使子例程递归调用自己,每次调用时仍然会取得一个新的@_。

×my操作符表示创建的变量是私有的,其作用范围被控制在所属的块中。my不加括号时只能声明一个词法变量,加括号时可以声明多个,如
my $fred, $barney; #错! $barney没有声明
my($fred, $barney); 正确,两个都声明了

×使用use strict编译命令可以让Perl的编译器对当前块或者源文件,强制执行一些确保良好程序设计的规则,就是说,不要太无纪律了,这样容易出错。
如果使用了use strict,Perl会要求你一定要用my来声明每个新的变量。
根据大部分人的建议,比整个屏幕长的程序都应该加上use strict。

 


TAG: Perl

 

评分:0

我来说两句

Open Toolbar