Perl笔记:09、其他控制结构

unless控制结构

unless控制结构与if控制结构恰恰相反,if是判断表达式为真才执行下面的语句块,unless则判断表达式为假就执行语句块。

如果unless控制结构中加入else子句的时候那就相当于将if...else的代码执行部分反过来写是一致的:

unless ( $mon =~ /^Feb/ ) {
print "This month has at least thirty days.\n" ;
} else {
print "Do you see what's going on here?\n" ;
}

if ( $mon =~ /^Feb/ ) {
print "Do you see what's going on here?\n" ;
} else {
print "This month has at least thirty days.\n" ;
}

相同

until控制结构

有时也许会想要颠倒while循环的条件。那么可以使用until

until($j>$i){
$j *=2;
}

这个循环回一直执行,直到条件为真。它只不过是个改装过的while循环罢了,两者之前唯一的差别在于until会在条件为假的时候重复执行。

条件修饰词

表达式后面可以接着一个用来控制它的修饰词,例如用if修饰词来模拟一个if快:
print "$n is a negative number.\n" if $n < 0;这一句代码相当于下列的语句块:

if ( $n < 0 ) {
print "$n is a negative number.\n" ;
}

除了if修饰词外,还有以下的修饰词:
&error("Invalid input") unless &valid($input);
$i
*=
2
until
$i
>
$j;
print " ", ($n += 2) while $n < 10;
&greet($_)
foreach
@person;

裸块控制结构

所谓的裸快控制结构是没有关键字或条件的代码块。不如现在有一个while循环,如下所示:
while (condition) {
body;
body;
body;
}
然后拿走关键字while和条件,就会得到一个裸块:
{
body;
body;
body;
}
裸块像一个while或foreach循环,可它从不循环,只执行一次。也就是一个伪循环!

裸块还有一个好处,就是可以在裸块里使用临时变量,而不会影响到全局变量。

elsif子句

许多情况下,你需要逐项检查一系列的条件表达式,看看其中哪个为真。这可以通过if控制结构的elsif子句来写成如下代码:

if ( ! defined $dino ) {
print "The value is undef.\n" ;
} elsif ( $dino =~ /^-?\d+\.?$/ ) {
print "The value is an integer.\n" ;
} elsif ( $dino =~ /^-?\d*\.\d+$/ ) {
print "The value is a _simple_ floating-point number.\n" ;
} elsif ( $dino eq '' ) {
print "The value is the empty string.\n" ;
} else {
print "The value is the string '$dino'.\n" ;
}

自增和自减

很简单与C/C++一致

for控制结构

很简单与C/C++一致

循环控制

last操作符

操作符last能立即终止循环。就像在C语言中的break操作符一样。当看到last,循环就会结束,例如:

# 输出所有包含 fred的行,直到碰到 __END__ 标记为止
while ( <STDIN> ) {
if ( /__END__/ ) {
# No more input on or after this marker line
last ;
} elsif ( /fred/ ) {
print ;
}
}
## last comes here #

只要输入行中有__END__记号,这个循环就会结束。

在Perl中有5中循环块。也就是for、foreach、while、until以及裸块而if块或者子程序带的花括号不是循环的快。last操作符对整个循环块起作用。

last操作符只会对运行中最内层的循环快发挥作用。

next操作符

next是跳过本次循环,像C中的continue一致。

redo操作符

redo操作符可以将控制返回到本次循环的顶端,不经过任何条件测试,也不会进入下一次循环迭代。而那些用过C语言的人们却对这个操作符感到陌生。因为C语言里没有这个概念。例子如下:

# 打字测试
my @words = qw { fred barney pebbles dino wilma betty } ;
my $errors = 0 ;
foreach ( @words ) {
## redo 会跳到这里 ##
print "Type the word '$_': " ;
chomp ( my $try = <STDIN> ) ;
if ( $try ne $_ ) {
print "Sorry - That's not right.\n\n" ;
$errors ++;
redo ; # 跳到循环的顶端
}
}
print "You've completed the test, with $errors errors.\n" ;

和另外两个操作符一样,redo在这5中循环快里都可以使用,并且在循环快嵌套的情况下只对最内层的循环起作用。

next和redo两者之前最大的区别在于next会正常继续下一次迭代,而redo则会重新执行这次的迭代。下面的例子可以然你体验这三种操作符工作方式的区别:

foreach ( 1 ..10 ) {
print "Iteration number $_.\n\n" ;
print "Please choose: last, next, redo, or none of the above? " ;
chomp ( my $choice = <STDIN> ) ;
print "\n" ;
last if $choice =~ /last/i ;
next if $choice =~ /next/i ;
redo if $choice =~ /redo/i ;
print "That wasn't any of the choices... onward!\n\n" ;
}
print "That's all, folks!\n" ;

三目操作符?:

perl里的三目操作符和C语言中的一致。
条件表达式真表达式:假表达式

逻辑操作符

&& / and 逻辑与
|| / or 逻辑或
! / not 逻辑非

if ( $dessert { 'cake' } && $dessert { 'ice cream' } ) {
# 两个条件都为真
print "Hooray! Cake and ice cream!\n" ;
} elsif ( $dessert { 'cake' } || $dessert { 'ice cream' } ) {
# 至少一个条件为真
print "That's still good...\n" ;
} else {
# 两个都为假——什么也不做
}

“定义或”操作符

在Perl 5.10中引入了“定义或”操作符//,在发现左边已定义的值时进行短路,无论作弊的只是真是假。这些定义或(defined-or)操作符会跟那些逻辑或操作符一样,只是它们测试的是是否已经定义,而不是布尔值。

use 5.010 ;
my $last_name = $last_name { $someone } // '(No last name)' ;

上面的含义为:如果last_name哈希中没有$someon的键时就是用//后面的值作为$last_name的值。

使用部分求值操作符的控制结构

之前看到的四个操作符 &&、 ||、 // 和?: 都有一个共性:根据左边的求值决定是否计算右侧的表达式。有些情况会执行的表达式,在另外的情况下并不执行。因此被统称为部分求值操作符,部分求值操作符是天然的控制结构,因为不会执行所有的表达式。

如果写过linux 下的shell脚本的话应该能够很快的了解这个部分求值操作符的说法,例如在linux 的shell中你可能写过如下的代码:
[ -e /etc/passwd ] && cat /etc/passwd
实际上在perl中也可以利用前面介绍的操作符来进行部分求值操作:
($m < $n) && ($m = $n); # 只有当$m的值小于$n的值时才会执行后面的操作
($m > 10) || print "why is it not greater?\n"; #当$m的值小于10时才会打印输出后面的内容。
三目操作符同样可以成为控制结构。下面的例子,我们想将$x赋值给两个变量中较小的那个:
($m < $n) ? ($m = $x) : ($n = $x);

“逻辑或”、“逻辑与”操作符的另外一种写法。可以讲他们写成单词or和and。这种单词的形式和标点符号的形式的效果是相同的,但是前者在运算优先级要低得多。既然单词操作符不会紧紧的粘住附近的表达式,它们需要的括号可能会少一些:
$m<$n and $m = $n; #写成相应的if语句版本会更好

另外一个常用的写法是:

open CHAPTER, $filename
or die "Can't open '$filename': $!";
通过使用低优先级的短路or操作符,我们表达了open this file or die的意思。如果文件打开成功,就会返回真,此时or就不必执行了;但如果文件打开失败,or就还得去执行右侧的部分,也就是丢出信息并终止程序。

====================本章习题=====================

1、编写程序,让用户不断猜测范围从1到100的秘密数字,直到猜中为止。程序应该以公式int(1+rand 100)来随进产生秘密数字。当用户猜错时,程序应该响应Too hight或Too low。如果用户键入quie或exit等字样,或者键入一个空白行,程序终止。当然用户猜到了,程序也终止。
答:

#!/usr/bin/perl -w

use strict ;

my $num = int ( 1 + rand 100 ) ;

while ( 1 ) {
print "please input number:" ;
chomp ( my $input = <STDIN> ) ;

if ( $input =~ /quit|exit|^\s*$/i ) {
print "You are a person without perseverance!\nbyebye!\n" ;
last ;
}
elsif ( $input > $num ) {
print "Too hight!\n" ;
}
elsif ( $input < $num ) {
print "Too low!\n" ;
}
elsif ( $input == $num ) {
print "Ok you are right!\n" ;
last ;
}
}

注意:这里的判断退出的语句一定要放到最前面,否则就会出错。该程序中使用了int和rand函数,rand 100 会生成0以上100以下的随机数,但要注意,并非是随机整数,因此有可能为99.999,因此我这里用 1+rand 100来操作,最后利用int函数取出整数部分。

2、修改迁前一个程序,打印额外的调试信息,例如程序选择的秘密数组。确保修改的部分可以用开关控制,并且调试开关即使关上也不会产生警告。如果使用Perl 5.10版本可以用//操作符,否则请使用三目操作符。
答:这个程序是在之前的解答基础上做了少量的修改。我们需要在开发过程中打印秘密数字,所以在$Debug变量为真的时候调用print。而$Debug的值要么来自于环境变量,要么是默认值1.通过使用//操作符,我们在$ENV{DEBUG}未定义的时候设置它为1:

my $debug = $ENV {DEBUG } ? $ENV {DEBUG } : 1 ;

print "this number is :$num\n" if $debug ;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值