1、编写并运行一个输出“Hello, world”的Perl程序,以此来测试Perl环境是否正常工作。
以下几种方式可实现“Hello, world”程序:
创建文件,内容为
perl
print "Hello, world!
";
运行
perl 文件名
;
若 Perl 版本为 v5.10 或更高,文件内容可写为
perl
use v5.10;
say "Hello, world!";
再运行。
不创建文件,在命令行使用
-e
开关:
bash
$ perl -e 'print "Hello, World
"'
使用
-l
开关自动添加换行符:
bash
$ perl -le 'print "Hello, World"'
在 Windows 的
command.exe
(或
cmd.exe
)中,引号使用要调整,如
cmd
C:> perl -le "print 'Hello, World'"
也可使用广义引号
cmd
C:> perl -le "print q(Hello, World)"
Perl v5.10 及更高版本使用
-E
开关启用新特性并使用
say
:
bash
$ perl -E 'say "Hello, World"'
2、编写一个程序,计算半径为 12.5 的圆的周长。圆的周长是 2π乘以半径(约为 2 乘以 3.141592654)。你得到的答案应该约为 78.5。
#!/usr/bin/perl
use warnings;
$pi = 3.141592654;
$radius = 12.5;
$circ = 2 * $pi * $radius;
print "The circumference of a circle of radius $radius is $circ.
";
3、编写一个 Perl 程序,提示用户输入一个圆的半径,然后计算并输出该圆的周长。例如,当用户输入的半径为 12.5 时,程序应计算并输出该半径对应的圆的周长。
#!/usr/bin/perl
use warnings;
$pi = 3.141592654;
print "What is the radius? ";
chomp($radius = <STDIN>);
$circ = 2 * $pi * $radius;
print "The circumference of a circle of radius $radius is $circ.
";
4、编写一个程序,提示用户输入两个数字(分别在不同的输入行),并输出这两个数字相乘的结果。
print 'Enter first number: ';
chomp($one = <STDIN>);
print 'Enter second number: ';
chomp($two = <STDIN>);
$result = $one * $two;
print "The result is $result.
";
5、编写一个程序,提示用户输入一个字符串和一个数字(分别在不同的输入行),然后将该字符串按照数字指定的次数分行输出。(提示:使用 x 运算符)。如果用户输入“fred”和“3”,输出应该是三行,每行都显示“fred”。如果用户输入“fred”和“299792”,可能会有大量输出。
以下是实现该功能的 Perl 代码示例:
print "请输入一个字符串:";
my $string = <STDIN>;
chomp($string);
print "请输入一个数字:";
my $number = <STDIN>;
chomp($number);
print ($string . "
") x $number;
这段代码首先提示用户输入一个字符串和一个数字,然后使用
x
运算符将字符串重复指定的次数,并在每次重复后添加换行符,最后将结果输出。
6、编写一个程序,逐行读取字符串列表,直到输入结束,然后按逆序输出该列表。如果输入来自键盘,在Unix系统上可能需要按Control – D,在Windows系统上可能需要按Control – Z来表示输入结束。
在 Perl 语言中,原答案
print reverse <>;
可以实现该功能,但表述不够完整。以下是一个更完整的 Python 实现示例:
lines = []
while True:
try:
line = input()
lines.append(line)
except EOFError:
break
for line in reversed(lines):
print(line)
7、编写一个程序,逐行读取一系列数字,直到输入结束。然后,针对每个输入的数字,从以下列表中打印出对应的人名。将这个人名列表硬编码到程序中,即它应出现在程序的源代码中。人名列表为:fred betty barney dino wilma pebbles bamm – bamm。例如,如果输入的数字是1、2、4和2,输出的人名将是fred、betty、dino和betty。
以下是一个Python示例代码来解决这个问题:
names = ['fred', 'betty', 'barney', 'dino', 'wilma', 'pebbles', 'bamm - bamm']
while True:
try:
num = int(input())
if 1 <= num <= len(names):
print(names[num - 1])
except EOFError:
break
以上代码定义了一个人名列表
names
,然后通过
while True
循环不断读取输入的数字,将输入的数字转换为整数后,检查其是否在有效范围内(1到列表长度),如果是则打印对应的人名。当遇到输入结束符(EOF)时,使用
try - except
语句捕获
EOFError
异常并跳出循环。
8、编写一个程序,逐行读取字符串列表,直到输入结束。然后,它应该按代码点顺序打印这些字符串。也就是说,如果你输入字符串 fred、barney、wilma、betty,输出应该显示 barney betty fred wilma。输出中的所有字符串是在一行上还是分行显示?你能让输出以这两种样式呈现吗?
如果想让输出在一行上,代码如下:
chomp(@lines = <STDIN>);
@sorted = sort @lines;
print "@sorted
";
若要分行显示,可去掉
chomp
去掉对换行符的处理,直接打印排序后的数组元素,如:
@lines = <STDIN>;
@sorted = sort @lines;
foreach my $line (@sorted) {
print $line;
}
9、编写一个名为total的子程序,它返回一个数字列表的总和。该子程序不应执行任何输入/输出操作,只需处理其参数并将一个值返回给调用者。编写一个示例程序来测试这个子程序,示例程序中定义一个数组my @fred = qw{ 1 3 5 7 9 }; 调用total子程序计算该数组元素的总和并输出结果,结果应为25。同时,程序还应从标准输入读取一些数字(每行一个数字),调用total子程序计算这些数字的总和并输出结果。注意,在列表上下文中使用
将等待你以适合你系统的方式结束输入。
以下是实现该功能的代码:
sub total {
my $sum = 0;
foreach (@_) {
$sum += $_;
}
return $sum;
}
10、编写一个程序来计算 1 到 1000 这些数字的总和,假设存在一个子程序 total 用于计算列表中数字的总和。
实现该功能的程序示例如下:
# Remember to include &total from previous exercise!
print "The numbers from 1 to 1000 add up to ", total(1..1000), ".
";
其中
total
子程序需提前定义,用于计算列表中数字的总和。
11、编写一个名为 above_average 的子程序,它接受一个数字列表,并返回那些高于平均值(均值)的数字。(提示:编写另一个子程序,通过将总和除以项数来计算平均值。)在以下测试程序中测试你的子程序:my @fred = above_average(1..10); print “@fred is @fred
”; print “(Should be 6 7 8 9 10)
“; my @barney = above_average(100, 1..10); print “@barney is @barney
“; print “(Should be just 100)
“;
以下是实现该功能的代码:
sub average {
if (@_ == 0) {
return
}
my $count = @_;
my $sum = total(@_);
$sum / $count;
}
sub above_average {
my $average = average(@_);
my @list;
foreach my $element (@_) {
if ($element > $average) {
push @list, $element;
}
}
@list;
}
其中,需要额外实现一个
total
子程序,用于计算数字列表的总和。
12、编写一个名为 greet 的子程序,通过告知被问候者上一个被问候者的名字来欢迎他们:执行 greet( “Fred” ); greet( “Barney” ); 这两条语句应输出:Hi Fred! You are the first one here! Hi Barney! Fred is also here!
use v5.10;
sub greet {
state $last_person;
my $name = shift;
print "Hi $name! ";
if( defined $last_person ) {
print "$last_person is also here!
";
} else {
print "You are the first one here!
";
}
$last_person = $name;
}
greet( 'Fred' );
greet( 'Barney' );
13、修改程序,让它能告诉每个新来的人之前所有被问候过的人的名字。执行以下语句序列:greet( “Fred” ); greet( “Barney” ); greet( “Wilma” ); greet( “Betty” ); 这些语句应该输出: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
使用v5.10版本及以上的Perl语言,代码如下:
```perl
use v5.10;
greet( 'Fred' );
greet( 'Barney' );
greet( 'Wilma' );
greet( 'Betty' );
sub greet {
state @names;
my $name = shift;
print "Hi $name! ";
if( @names ) {
print "I've seen: @names";
} else {
print "You are the first one here!";
}
push @names, $name;
}
14、编写一个程序,其功能类似于 cat 命令,但要将输出行的顺序反转。(有些系统有一个类似的实用工具名为 tac)。如果你以 ./tac fred barney betty 运行该程序,输出应该是文件 betty 的所有行按从最后一行到第一行的顺序,接着是 barney 的,然后是 fred 的,同样按从最后一行到第一行的顺序。(如果你将程序命名为 tac,调用时一定要使用 ./ ,以免调用到系统自带的实用工具)
以下是一个用 Python 实现的示例代码:
import sys
for filename in reversed(sys.argv[1:]):
try:
with open(filename, 'r') as file:
lines = file.readlines()
for line in reversed(lines):
print(line.rstrip())
except FileNotFoundError:
print(f"文件 {filename} 未找到。")
将上述代码保存为
tac.py
,然后在命令行中使用
python tac.py fred barney betty
来运行程序。如果要实现和题目中一样的调用方式,需要将代码保存为
tac
并赋予执行权限,然后使用
./tac fred barney betty
调用。
15、编写一个程序,要求用户在不同的行上输入一系列字符串,将每个字符串右对齐打印在一个20字符宽的列中。为确保输出在正确的列中,同时打印一行数字作为“标尺线”(这只是一个调试辅助工具)。确保不要误使用19字符宽的列!例如,输入hello、good – bye,输出应类似如下:123456789012345678901234567890123456789012345678901234567890
hello
good - bye
以下是实现该功能的Perl代码:
print "Enter some lines, then press Ctrl-D:
"; # or Ctrl-Z
chomp(my @lines = <STDIN>);
print "1234567890" x 7, "12345
"; # ruler line to column 75
foreach (@lines) {
printf "%20s
", $_;
}
16、修改之前的程序,让用户选择列宽,这样输入 30、hello、good – bye(分行输入)时会将字符串显示在第 30 列。额外加分项:当选定的宽度较大时,让标尺线更长。
以下是实现代码:
print "What column width would you like? ";
chomp(my $width = <STDIN>);
print "Enter some lines, then press Ctrl - D:
"; # or Ctrl - Z
chomp(my @lines = <STDIN>);
print "1234567890" x (($width + 9)/10), "
"; # ruler line as needed
foreach (@lines) {
printf "%${width}s
", $_;
}
或者使用:
foreach (@lines) {
printf "%*s
", $width, $_;
}
17、编写一个程序,要求用户输入一个名字,并输出对应的姓氏。名字和姓氏的对应关系如下:fred 对应 flintstone,barney 对应 rubble,wilma 对应 flintstone。
以下是一个满足需求的Perl程序示例:
use strict;
use warnings;
# 定义名字和姓氏的映射
my %name_map = (
'fred' => 'flintstone',
'barney' => 'rubble',
'wilma' => 'flintstone'
);
# 提示用户输入名字
print "请输入一个名字: ";
# 获取用户输入
my $given_name = <STDIN>;
chomp $given_name;
# 获取对应的姓氏
my $family_name = $name_map{lc $given_name};
# 输出结果
if ($family_name) {
print "对应的姓氏是: $family_name
";
} else {
print "未找到对应的姓氏。
";
}
18、编写一个程序,逐行读取一系列单词,直到输入结束,然后输出每个单词出现的次数总结。例如,如果输入的单词是 fred、barney、fred、dino、wilma、fred(每行一个单词),输出应表明 fred 出现了 3 次。额外加分项:按代码点顺序对输出的总结单词进行排序。
以下是实现该功能的 Perl 代码:
my(@words, %count, $word);
chomp(@words = <STDIN>);
foreach $word (@words) {
$count{$word} += 1;
}
foreach $word (sort keys %count) {
print "$word was seen $count{$word} times.
";
}
19、修改一个程序,使其也能匹配“Fred”。判断当输入字符串是“Fred”、“frederick”或“Alfred”时,程序是否能匹配。(假设可以在文本文件中添加包含这些名称的行)
修改方法是将之前程序中使用的模式改为
/[fF]red/
,也可以尝试
/(f|F)red/
或
/fred|Fred/
,但字符类更高效。
对于输入字符串:
– “Fred” 能匹配
– “frederick” 不匹配(当前逻辑)
– “Alfred” 中 “fred” 会匹配(当前逻辑)
注意:当前版本中要求匹配全词的功能尚未实现。后续会学习实现该功能,以修正“frederick”和“Alfred”的匹配行为。
20、编写一个程序,对文本文件进行修改并生成副本。在副本中,每个字符串 Fred(不区分大小写)应替换为 Larry。(例如,Manfred Mann 应变为 ManLarry Mann。)输入文件名应在命令行中给出(不要询问用户),输出文件名应为对应的以 .out 结尾的文件名。
my $in = $ARGV[0];
if (! defined $in) {
die "Usage: $0 filename";
}
my $out = $in;
$out =~ s/(.w+)?$/.out/;
if (! open $in_fh, '<', $in ) {
die "Can't open '$in': $!";
}
if (! open $out_fh, '>', $out ) {
die "Can't write '$out': $!";
}
while (<$in_fh>) {
s/Fred/Larry/gi;
print $out_fh $_;
}
21、编写一个程序,该程序会反复要求用户猜测一个1到100之间的秘密数字,直到用户猜对为止。程序应使用神奇公式 int(1 + rand 100) 随机选取数字。当用户猜错时,程序应回应“Too high”或“Too low”。如果用户输入“quit”或“exit”,或者输入空行,程序应退出。当然,如果用户猜对了,程序也应退出!
以下是对应的 Perl 代码:
my $secret = int(1 + rand 100);
while (1) {
print "Please enter a guess from 1 to 100: ";
chomp(my $guess = <STDIN>);
if ($guess =~ /quit|exit|As*z/i) {
print "Sorry you gave up. The number was $secret.
";
last;
}
elsif ($guess < $secret) {
print "Too low. Try again!
";
}
elsif ($guess == $secret) {
print "That was it!
";
last;
}
else {
print "Too high. Try again!
";
}
}
22、修改一个程序,使其在运行过程中打印额外的调试信息,比如它选择的秘密数字。进行修改,以便可以关闭该调试信息输出,并且当关闭时程序不会发出警告。如果你使用的是 Perl 5.10 或更高版本,使用 // 运算符。否则,使用条件运算符。
下面是给定的【文本内容】:
使用 Perl 5.10 或更高版本:
```perl
use v5.10;
my $Debug = $ENV{DEBUG} // 1;
my $secret = int(1 + rand 100);
print "Don't tell anyone, but the secret number is $secret.
" if $Debug;
不使用 Perl 5.10 及以上版本:
my $Debug = defined $ENV{DEBUG} ? $ENV{DEBUG} : 1;
my $secret = int(1 + rand 100);
print "Don't tell anyone, but the secret number is $secret.
" if $Debug;
23、编写一个程序,找出命令行中指定的最旧的文件,并报告其存在的天数。如果文件列表为空(即命令行中未提及任何文件),程序会怎样?
如果文件列表为空,程序会报错,提示没有提供文件名,因为没有文件可供检查,也就不存在最旧的文件。示例代码如下:
die "No file names supplied!" unless @ARGV;
24、编写一个程序,使用堆叠文件测试操作符列出命令行中指定的所有可读、可写且归当前用户所有的文件。
以下是一个使用Perl编写的示例程序来实现该功能:
#!/usr/bin/perl
use v5.10;
foreach my $filename (@ARGV) {
if (-r -w -o $filename) {
print "$filename 是可读、可写且归你所有的文件。
";
}
}
将上述代码保存为一个文件(例如
test.pl
),然后在命令行中运行,例如:
perl test.pl file1 file2 file3
程序将列出所有可读、可写且归当前用户所有的文件。