《Perl语言入门》第15章习题第2题如下:
用 given-when 结构写一个程序,根据输入的数字,如果它能被3整除,就打印“Fizz”;如果它能被5整除,就打印“Bin”;如果它能被7整除,就打印“Sausage”。比如,如果输入15,程序就应该打印“Fizz”和“Bin”,因为15可以同时被3和5整除。思考一下,可以让程序输出“Fizz Bin Sausage”的最小数字该是多少?
自己写的程序如下:
#!/usr/bin/perl 2 use 5.010; 3 my $num; 4 while(chomp($num=<STDIN>)){ 5 next unless $num =~ /\A\d+\.?\d+\z/; #防止输入的内容不是数字 6 given($num){ 7 when( not $_%3 ){ 8 print "Fizz "; 9 continue; 10 } 11 when( not $_%5 ){ 12 print "Bin "; 13 continue; 14 } 15 when( not $_%7 ){ 16 print "Sausage "; 17 continue; 18 } 19 default { print "\n";} 20 } 21 }
结果运行的时候,发现输入 3 、5 、7 ,没有任何输出,而输入 15、 35 、21 之类的数字,却可以有 “Fizz Bin”、 “Bin Sausage” 之类的输出,怎么回事呢?
仔细推敲,原来问题出在第5行的正则表达式的代码上:
该行代码的本意是测试输入的内容是否为数字,如果不是数字,则进入下一次循环,读取下一次的输入;但匹配的模式中,'\d+' 要求至少匹配一个数字字符,则两个'\d+'则要求至少匹配两个数字字符。于是,当输入为 3 、 5、 7 的时候,因为是单个数字字符,因而无法正常匹配,就进入了下一次的循环。解决方案是使用 '/\A\d+\.?\d?/' 这个模式进行匹配。
#!/usr/bin/perl 2 use 5.010; 3 my $num; 4 while(chomp($num=<STDIN>)){ 5 next unless $num =~ /\A\d+\.?\d?\z/; #防止输入的内容不是数字 6 given($num){ 7 when( not $_%3 ){ 8 print "Fizz "; 9 continue; 10 } 11 when( not $_%5 ){ 12 print "Bin "; 13 continue; 14 } 15 when( not $_%7 ){ 16 print "Sausage "; 17 continue; 18 } 19 default { print "\n";} 20 } 21 }
问题解决!