Perl语言入门 (08 自定义函数)

由于公司需要,本人最近在学习Perl这种脚本语言,本文是我在学习Perl的过程中总结出来的一些心得和笔记,希望能够帮助也在学习Perl的各位同僚。废话不多说直接上干货!!!

—————————————————————————— 干货分割线 ——————————————————————————

Pe r l中,用户定义的函数称为子例程.子例程可以在任何位置被调用,包括在其他子例程中调用.

创建函数:

sub 函数名{

    代码语句;

        ...

    代码语句;

}

Exp:

sub yesno{

    Print “R U sure?”;

    $answer = <STDIN>;

}

调用子例程的两种方法:

1.$yesno();  #任何位置都可以使用该方法

2. yesno();  #代码中已经声明了子例程可以使用该方法.

 

Exp:

sub countdown{

    for($i = 10; $i >=0; $i--){

        print “$i  -”;

    }

}

Print “T-minus:”;

Countdown();

Print “Blastoff”;

 

子例程的返回值:子例程的返回值是它的内部计算的最后一个表达式的值或者是return语句显示返回的值.

Exp:

1.不用return关键字:

Sub two_by_four{

2*4; #此处与Java不同,可不写return关键字;

}

Print 8 * two_by_four();  #输出 64;

 

2.使用return关键字:

当程序需要在子例程结束前返回,或当想要知道返回的是什么值,而不是想要执行到最后表达式的值时,就需要使用r e t u r n语句。

Exp:

my $x = 70;
if(x_greaterthan100()){
    Print “$x is greater than 100\n”;
}else{
    print “子例程返回为0.所以在if中无输出\n”;
}
Sub x_greaterthan100{
    Return(1) if($x > 100);
    0;
}

PS:最好把子函数写在父函数后面,这样在传递参数时便不会提示警告.

 

子例程能够返回数组和哈希结构,也能返回标量.

Exp:

#!/usr/bin/perl  
use strict;  
use warnings;
 
my @a = shift_to_upper();
for(my $i = 0; $i <= $#a; $i++){
    print "$a[$i]\n";
}
 
sub shift_to_upper{
    my @words = qw(cia fbi un nato unicef);
    foreach(@words){
        $_ = uc($_);  #小写转化为大写
    }
    return (@words);
}

子例程传递参数的写法:

Subname(arg1,arg2,arg3);

Subname arg1,arg2,arg3; #该子例程被定义后,才能使用该写法

$subname(arg1,arg2,arg3);

 

在写子函数时,有两种写法:

1. Sub subroutine($$){},该方法要求在调用该方法时必须传递两个参数;

2. sub subroutine(){},该方法对传参个数没有严格要求。

 

在子例程中,被传递的参数可以通过P e r l的特殊变量@ 来访问。下面这个代码段显示了为函数传递参数(3个字符串直接量)和输出参数的情况:

#!/usr/bin/perl
  
use strict;  
use warnings;
 
sub printargs{
    print join(',',@_);  #参数通过@_传递过来(3个字符串直接量)
}
printargs('aaa','bbb','ccc ddd');

输出:aaa,bbb,ccc ddd

exp: 

use strict;  
use warnings;
 
sub display_box_score{
    (my $hits,my $at_bats) = @_;    #  =@_;  为固定写法,只要注意传递的参数个数即可
    print "这里的hits为:$hits\n";
    print "这里的at_bats为:$at_bats\n";
}
display_box_score(50,210);

PS:

1.当参数为1个时,输出为:

 

因为at_bats没有参数,所以报错;

2.当参数个数>2时,不影响程序结果,只是后面的参数没有接收到而已

3.@ _包含了传递给子例程的原始参数的别名。如果修改了@ _(或者修改了@ 的任何元素),就会修改参数列表中的元素变量。

 

传递数组和Hash结构

1.一个参数时

@sorted_items = sort_numberically(@items);

Sub sort_numberically{

    Print “sorting …”;

    Return (sort{$a ó $b} @_);

}

PS:在该子例程中,@items通过@_进行引用

 

2.多个参数时

Exp:

Display_arrays(@first,@second);

Sub Display_arrays{

    (@a,@b) = @_;

    Print “The first array:@a\n”;

    Print “The second array:@b\n”;

}

输出:The first array:[@_的全部值]

报错

The second array:[空值]

PS: @b并不会得到参数;

3.参数为标量和Hash时:

参数为混合体时,只要标量在参数列表中首先被传递,且知道有多少个标量。

Exp:

Sub lots_of_args{

    ($first,$second,%hash) = @_;

}

lots_of_args($foo,$bar,%myhash);

作用域:

Exp1:

$weight = 150;

Print moonweight;

Sub moonweight{

    Return ($weight/6);

}

PS:

缺点:全局变量$weight传递给子函数,且必须确保正确设置$weight.

Exp2(升级版):

Print moonweight(150);

Sub moonweight{

    ($weight) = @_;

    Return ($weight / 6);

}

PS:

优点:不必设置外部变量,将参数自然而然传递给子函数内部。

 

函数嵌套调用的例子:

#!/usr/bin/perl  
#use strict;  
#use warnings;
 
print "please enter data,separated by commas:\n";
my ($data,@dataset);
$data = <STDIN>; chomp $data; #从终端输入放入标量中
@dataset = split(/[\s,]+/,$data); #将标量按照某种格式分割,放入数组  /[\s,]+/:匹配多个空格或,
 
print "Median:",median(@dataset),"\n";
print "Mean:",mean(@dataset),"\n";
print "Standard Dev.:",std_dev(@dataset),"\n";
 
#求数组中元素的个数
sub mean{
    my (@data) = @_; #从外部接受数据时定义的标量加()
    my $sum;
    foreach(@data){
        $sum += @_;dsf
    }
    return ($sum / @data);
}
 
#返回数组中间的数,若为偶数,则返回两个数的平均值
sub median{
    my (@data) = sort {$a <=> $b} @_;  #将原数组重新排序
    if(scalar (@data) % 2){
        return ($data [@data / 2]);  #@data/2的返回值向上取整
    }else {
        my ($upper ,$lower);
        $upper = $data[@data / 2];
        $lower = $data[@data / 2 -1];
        return (($lower+$upper) / 2);
    }
}
 
sub std_dev{
    my (@data) = @_;
    my ($sq_dev_sum,$avg) = (0,0);
    $avg = mean(@data);
    foreach my $elem(@data){
        $sq_dev_sum += ($avg - $elem) ** 2;
    }
    return (sqrt($sq_dev_sum / @data - 1));
}

声明Local变量:

Exp:

Sub myfunc{

    Local($foo) = 56;

}

local声明的变量和用my几乎相同。差别是:声明为局部变量的那些变量,可以在它的作用域范围内的代码块中看到,也可以在从该代码块中调用的任何子例程中看到。基本都用my生命而不用local.

 

 

 


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值