本章要點:
(1)在perl里,&fred和$fred雖然名字一樣馏艾,但是是兩種東西奴愉。一個是調(diào)用名為fred的子程序;一個是名為fred的標(biāo)量锭硼。
(2)用sub來定義子程序,并用{}來界定子程序的內(nèi)容轰异。
(3)如果你在一個腳本里定義了兩個名字相同的子程序,第二個將會覆蓋第一個搭独。
(4)調(diào)用子程序,使用&字符唉俗。比如:&marine配椭。但是這個符號是可以省略的,除非你的子程序名字與perl的內(nèi)置函數(shù)名字相同股缸,如果是這樣的情況,就必須用&來調(diào)用你的子程序寺酪。
(5)想要立即終止子程序替劈,使用return寄雀。
(6)使用my陨献,可以在子程序里設(shè)置變量,盡管每次調(diào)用子程序時急膀,必須再次定義它們龄捡。使用state,可以將私有變量的作用域限定在子程序中聘殖,但是Perl將在每次調(diào)用之間保留它們的值。
(7)defined:判斷一個值是否是undef而不是空字符串餐禁,使用defined函數(shù)突照,該函數(shù)對undef返回false,對其他所有值返回true:
$next_line = <STDIN>;
if ( defined($next_line) ) {
print "The input was $next_line";
} else {
print "No input available!\n";
}
(8)shift:去掉數(shù)組里的第一個元素。也就是卸載參數(shù)筑舅,當(dāng)你只需要一個參數(shù)時使用shift庄岖;讀取多個參數(shù)時使用列表賦值角骤。(參考:第五章 Perl函數(shù))。
參考文章:
1.Perl 變量
2.第五章 Perl函數(shù)
課后練習(xí):
第一題:
Write a subroutine, named total, which returns the total of a list of numbers.
Hint: the subroutine should not perform any I/O; it should simply process
its parameters and return a value to its caller. Try it out in this sample program,
which merely exercises the subroutine to see that it works. The first group of
numbers should add up to 25.
my @fred = qw{ 1 3 5 7 9 };
my $fred_total = total(@fred);
print "The total of \@fred is $fred_total.\n";
print "Enter some numbers on separate lines: ";
my $user_total = total(<STDIN>);
print "The total of those numbers is $user_total.\n";
Note that using <STDIN> in list context like that will wait for you to end input in
whatever way is appropriate for your system.
腳本:
#!/usr/bin/perl
use warnings;
use v5.24;
sub total {
my $sum;
foreach ( @_ ) {
$sum += $_;
}
$sum;
}
my @fred = qw{ 1 3 5 7 9 };
my $fred_total = total(@fred);
print "The total of \@fred is $fred_total.\n";
print "Enter some numbers on separate lines:\n";
my $user_total = total(<STDIN>);
print "The total of those numbers is $user_total.\n";
$ ./practice.pl
The total of @fred is 25.
Enter some numbers on separate lines:
6
8
3
The total of those numbers is 17.
第二題
Using the subroutine from the previous problem, make a program to calculate
the sum of the numbers from 1 to 1,000.
腳本:
#!/usr/bin/perl
use warnings;
use v5.24;
sub total {
my $sum;
foreach ( @_ ) {
$sum += $_;
}
$sum;
}
my @fred = (1..1000);
my $fred_total = total(@fred);
print "The total of 1 to 1000 is $fred_total.\n";
運行結(jié)果:
$ ./practice.pl
The total of 1 to 1000 is 500500.
第三題
Extra credit exercise: write a subroutine, called &above_average, which takes
a list of numbers and returns the ones above the average (mean). (Hint: make
another subroutine that calculates the average by dividing the total by the number
of items.) Try your subroutine in this test program:
my @fred = above_average(1..10);
print "@fred is @fred\n";
print "(Should be 6 7 8 9 10)\n";
my @barney = above_average(100, 1..10);
print "@barney is @barney\n";
print "(Should be just 100)\n";
腳本:
#!/usr/bin/perl
use warnings;
use v5.24;
sub total {
my $sum;
foreach (@_){
$sum +=$_;
}
$sum;
}
sub average {
my $count =@_; #數(shù)組賦值給標(biāo)量,返回數(shù)組元素個數(shù)
my $sum =total(@_); #調(diào)用上一個子程序total蝉揍,這里省略了&符號
$sum/$count;
}
sub above_average {
my $average = average(@_); #調(diào)用上一個子程序average
my @list;
foreach my $number (@_){
if ($number > $average){
push @list,$number; #push的意思是把元素添加到list的最后
}
}
@list; #返回添加完所有符合要求的元素的list
}
my @fred = &above_average(1..10);
print "@fred is @fred\n";
print "(Should be 6 7 8 9 10)\n";
my @barney = &above_average(100, 1..10);
print "@barney is @barney\n";
運行:
$ ./practice.pl
6 7 8 9 10 is 6 7 8 9 10
(Should be 6 7 8 9 10)
100 is 100
(Should be just 100)
第四題
Write a subroutine named greet that welcomes the person you name by telling
them the name of the last person it greeted:
greet( "Fred" );
greet( "Barney" );
This sequence of statements should print:
Hi Fred! You are the first one here!
Hi Barney! Fred is also here!
腳本:
#!/usr/bin/perl
use warnings;
use v5.24;
sub greet {
state $last_person; #state聲明變量又沾,使該變量為本子程序私有變量
my $name = shift; #標(biāo)量name里只需要一個參數(shù),使用shift卸載參數(shù)
print "Hi $name! ";
if( defined $last_person ) {
print "$last_person is also here!\n";
}
else {
print "You are the first one here!\n";
}
$last_person = $name;
}
greet( 'Fred' ); #當(dāng)?shù)谝粋€參數(shù)賦值為Fred時杖刷,name標(biāo)量的undef被Fred取代,執(zhí)行打印“Hi Fred!”役听。而defined判斷l(xiāng)ast_person是空字符串表窘,所以if循環(huán)執(zhí)行else的命令。隨后乐严,name的參數(shù)傳遞給last_person。
greet( 'Barney' );#第二次調(diào)用子程序的時候昂验,name標(biāo)量被Barney取代,執(zhí)行操作打印“Hi Barney!”黍匾。這時if循環(huán)里呛梆,defined判斷l(xiāng)ast_person標(biāo)量里不是空字符串锐涯,而是之前name傳遞過來的Fred填物,所以執(zhí)行第一條命令打印“Fred is also here!”
運行結(jié)果:
$ ./practice1.pl
Hi Fred! You are the first one here!
Hi Barney! Fred is also here!
第五題
Modify the previous program to tell each new person the names of all the
people it has previously greeted:
greet( "Fred" );
greet( "Barney" );
greet( "Wilma" );
greet( "Betty" );
This sequence of statements should print:
Hi Fred! You are the first one here!
Hi Barney! I've seen: Fred
Hi Wilma! I've seen: Fred Barney
Hi Betty! I've seen: Fred Barney Wilma
腳本:
#!/usr/bin/perl
use warnings;
use strict;
use v5.24;
sub greet {
state $last_person;
state @name; #定義一個數(shù)組
my $name;
foreach my $name(@_){
print "Hi $name! "; #打印出標(biāo)量
if( defined $last_person ) {
print "I'v seen: @name\n"; #這里打印出數(shù)組里全部參數(shù),所以每調(diào)用一次升薯,打印的參數(shù)就會多一個
}
else {
print "You are the first one here!\n";
}
$last_person = $name;
push @name, $name;#每運行一次,把參數(shù)添加到@name數(shù)組里
}
}
greet( 'Fred' );
greet( 'Barney' );
greet( 'Wilama');
greet(' betty');
運行結(jié)果:
$ ./practice1.pl
Hi Fred! You are the first one here!
Hi Barney! I'v seen: Fred
Hi Wilama! I'v seen: Fred Barney
Hi betty! I'v seen: Fred Barney Wilama