table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
pre {
background-color: #f8f8f8;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
}
1、当方括号内的数字37出现在一道练习题文本开头时,它代表什么意思?
这个数字是对完成该特定练习题预计所需分钟数的大致估计。不过这个估计比较粗略,实际完成时间可能是预计时间的一半,也可能两倍都不止。
2、输入一个程序,使其输出“Hello, world”并运行。你可以随意命名该程序。
以下几种方式可实现“Hello, world”程序:
编写文件:
在文件中写入
perl
print "Hello, world!
";
若使用 v5.10 或更高版本,可使用
perl
use v5.10;
say "Hello, world!";
命令行运行:
使用
-e
开关指定程序,如
bash
$ perl -e 'print "Hello, World
"'
使用
-l
开关自动添加换行符,如
bash
$ perl -le 'print "Hello, World"'
Windows 系统命令行使用双引号在外,如
cmd
C:> perl -le "print 'Hello, World'"
也可使用广义引号,如
cmd
C:> perl -le "print q(Hello, World)"
v5.10 及更高版本使用
-E
开关启用新特性以使用
say
,如
cmd
C:> perl -E'say "Hello, world!"'
3、编写一个程序,计算半径为 12.5 的圆的周长。圆的周长是 2π 乘以半径(约为 2 乘以 3.141592654)。
以下是两种实现该功能的 Perl 程序示例:
示例一:
#!/usr/bin/perl
use warnings;
$pi = 3.141592654;
$circ = 2 * $pi * 12.5;
print "The circumference of a circle of radius 12.5 is $circ.
";
示例二:
#!/usr/bin/perl
use utf8;
use warnings;
$π = 3.141592654;
$circ = 2 * $π * 12.5;
print "The circumference of a circle of radius 12.5 is $circ.
";
4、编写一个程序,提示用户输入圆的半径,然后根据输入的半径计算并输出该圆的周长。例如,如果用户输入的半径为 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.
";
5、编写一个程序,提示用户输入两个数字(分别在不同的输入行),并输出这两个数字相乘的结果。
以下是实现该功能的程序示例:
print "Enter first number: ";
chomp($one = <STDIN>);
print "Enter second number: ";
chomp($two = <STDIN>);
$result = $one * $two;
print "The result is $result.
";
6、编写一个程序,提示用户输入一个字符串和一个数字(分别在不同的输入行),并将该字符串按照数字指定的次数打印在不同的行上。(提示:使用 x 运算符)。如果用户输入“fred”和“3”,输出应该是三行,每行都显示“fred”。如果用户输入“fred”和“299792”,可能会有大量输出。
以下是实现该功能的程序:
print "Enter a string: ";
$str = <STDIN>;
print "Enter a number of times: ";
chomp($num = <STDIN>);
$result = $str x $num;
print "The result is:$result";
该程序首先提示用户输入一个字符串,然后提示输入一个数字。使用
x
运算符将字符串重复指定的次数,并将结果存储在
$result
变量中。最后,将结果打印输出。
不过原答案中说能确保每个字符串都在单独的行上存在问题,因为输入的字符串本身可能没有换行符,若要保证每行一个字符串,可修改代码如下:
print "Enter a string: ";
$str = <STDIN>;
chomp($str); # 去除字符串末尾的换行符
print "Enter a number of times: ";
chomp($num = <STDIN>);
for (my $i = 0; $i < $num; $i++) {
print $str. "
";
}
修改后的代码使用循环每次打印字符串并添加换行符,确保每个字符串都在单独的行上。
7、编写一个程序,逐行读取字符串列表,直到输入结束,然后按逆序输出该列表。如果输入来自键盘,在Unix系统中可能需要按Ctrl – D,在Windows系统中可能需要按Ctrl+Z来表示输入结束。
以下是两种实现方式:
方式一:
print "Enter some lines, then press Ctrl - D:
";
@lines = <STDIN>;
@reverse_lines = reverse @lines;
print @reverse_lines;
方式二(更简洁):
print "Enter some lines, then press Ctrl - D:
";
print reverse <STDIN>;
大多数Perl程序员会更喜欢第二种方式,只要他们不需要保留这些行的列表以供后续使用。
8、编写一个程序,逐行读取字符串列表,直到输入结束。然后按码点顺序打印这些字符串。也就是说,如果你输入字符串 fred、barney、wilma、betty,输出应该是 barney betty fred wilma。输出的所有字符串是在一行上还是分行显示?你能让输出以这两种样式呈现吗?
以下是两种实现方式:
若要将输出显示在一行上,代码为:
perl
chomp(@lines = <STDIN>); @sorted = sort @lines; print "@sorted
";
若要分行显示输出,代码为:
perl
print sort <STDIN>;
9、编写一个名为 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(@_); # 假设 total 子程序已在之前定义
$sum / $count;
}
sub above_average {
my $average = average(@_);
my @list;
foreach my $element (@_) {
if ($element > $average) {
push @list, $element;
}
}
@list;
}
其中,
average
子程序用于计算平均值,
above_average
子程序用于返回高于平均值的数字列表。注意,代码中使用了
total
子程序,需要确保该子程序已经在之前定义。
10、编写一个名为 greet 的子程序,在欢迎你指定的人时,告诉他们上一个被问候的人的名字。例如执行 greet( “Fred” ); greet( “Barney” ); 这组语句应该输出:Hi Fred! You are the first one here! Hi Barney! Fred is also here!
以下是实现该功能的代码:
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' );
11、修改程序,实现当调用 greet 函数时,告知每个新到来的人之前所有被问候过的人的名字。运行如下语句: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
以下是实现该功能的代码:
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;
}
12、编写一个程序,功能类似于 cat 命令,但将输出行的顺序反转(有些系统有类似的名为 tac 的实用工具)。如果以 ./tac fred barney betty 运行该程序,输出应该是文件 betty 从最后一行到第一行的内容,接着是 barney 的内容(同样从最后一行到第一行),最后是 fred 的内容(也是从最后一行到第一行)。(如果程序名为 tac,调用时一定要使用 ./ ,以免调用系统自带的实用工具)
以下是一个用 Perl 编写的
tac
程序示例:
#!/usr/bin/perl
foreach my $file (reverse @ARGV) {
open(my $fh, '<', $file) or die "无法打开文件 $file: $!";
my @lines = <$fh>;
close($fh);
print reverse @lines;
}
13、编写一个程序,要求用户在不同行输入一系列字符串,将每个字符串打印在一个右对齐、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
", $_;
}
代码解释:
首先提示用户输入一些行,然后按 Ctrl – D(或 Ctrl – Z)结束输入。
使用
chomp
函数去除输入行末尾的换行符,并将输入的所有行存储在数组
@lines
中。
打印标尺线,这里重复“1234567890”七次并追加“12345”,以达到 75 列的标尺效果。
通过
foreach
循环遍历
@lines
数组,使用
printf
函数以
%20s
格式打印每个字符串,实现右对齐且宽度为 20 个字符的输出效果。
14、修改之前的程序,让用户选择列宽,例如依次输入 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
", $_;
}
代码解释:
获取列宽
:程序首先提示用户输入所需的列宽,并将用户输入存储在变量
$width
中,使用
chomp
去除换行符。
获取输入行
:接着提示用户输入一些行,按 Ctrl – D(或 Ctrl – Z)结束输入,将输入的行存储在数组
@lines
中,同样使用
chomp
去除换行符。
生成标尺行
:根据用户输入的列宽,使用
print "1234567890" x (($width + 9) / 10), "
"
生成标尺行,确保标尺行至少和所需宽度一样长。
输出字符串
:遍历输入的每一行,使用
printf "%${width}s
", $_
将字符串输出在指定的列宽位置。
关于变量插值:
使用
${width}
进行变量插值,需要使用花括号将变量名与后面的字符隔离开,避免插值错误的变量。若忘记使用花括号,也可以用
'%' . $width . "
"
得到相同的格式字符串。
注意事项:
使用
chomp
去除
$width
中的换行符很重要,否则生成的格式字符串会包含换行符,导致输出不符合预期。
15、编写一个程序,向用户询问名字并报告对应的姓氏。已知名字和姓氏的对应关系如下:fred 对应 flintstone,barney 对应 rubble,wilma 对应 flintstone。
以下是一个满足需求的 Perl 程序示例:
# 创建一个哈希表来存储名字和姓氏的对应关系
my %name_mapping = (
'fred' => 'flintstone',
'barney' => 'rubble',
'wilma' => 'flintstone'
);
# 提示用户输入名字
print "请输入一个名字: ";
my $given_name = <STDIN>;
chomp $given_name; # 去除换行符
# 将输入的名字转换为小写,以便匹配哈希表中的键
$given_name = lc $given_name;
# 检查输入的名字是否在哈希表中
if (exists $name_mapping{$given_name}) {
print "对应的姓氏是: $name_mapping{$given_name}
";
} else {
print "未找到对应的姓氏。
";
}
这个程序首先创建了一个哈希表
%name_mapping
,用于存储名字和姓氏的对应关系。然后提示用户输入一个名字,去除输入中的换行符,并将其转换为小写。接着检查输入的名字是否在哈希表中,如果存在则输出对应的姓氏,否则输出未找到的提示信息。
16、编写一个程序,读取一系列单词(每行一个单词)直到输入结束,然后打印出每个单词出现的次数总结。(提示:记住当一个未定义的值被当作数字使用时,Perl 会自动将其转换为 0。回顾之前记录累计总数的练习可能会有帮助。)所以,如果输入的单词是 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.
";
}
代码解释:
首先声明所需变量,使用
<STDIN>
读取所有输入行到
@words
数组并去除换行符。接着使用
foreach
循环遍历
@words
数组,对于每个单词,将其在
%count
哈希表中的计数加 1。最后,再次使用
foreach
循环遍历
%count
哈希表的键(按代码点顺序排序),并打印每个单词及其出现次数。
17、编写一个程序,列出 %ENV 中的所有键和值。以 ASCII 码顺序将结果打印成两列。若想获得额外加分,可使输出的两列垂直对齐。可以使用 length 函数来确定第一列的宽度。程序运行后,尝试设置一些新的环境变量,并确保它们显示在输出中。
以下是实现该功能的代码:
use v5.10;
$ENV{ZERO} = 0;
$ENV{EMPTY} = '';
$ENV{UNDEFINED} = undef;
my $longest = 0;
foreach my $key ( keys %ENV ) {
my $key_length = length( $key );
$longest = $key_length if $key_length > $longest;
}
foreach my $key ( sort keys %ENV ) {
printf "%-${longest}s %s
", $key, $ENV{$key} // "(undefined value)";
}
这段代码首先设置了几个环境变量,然后找出所有键中最长的长度,最后按 ASCII 码顺序遍历所有键,使用
printf
函数将键和值以两列形式输出,并使两列垂直对齐。对于未定义的值,会显示
(undefined value)
。
18、编写一个程序,打印输入中提到“fred”的每一行,而对其他行不做处理。如果输入字符串是“Fred”、“frederick”或“Alfred”,是否会匹配?创建一个包含几行提及“fred flintstone”及其朋友的小文本文件,然后将该文件作为此程序的输入。
此问题要求编写程序筛选出包含“fred”的行,对于输入“Fred”、“frederick”、“Alfred”,只有“fred”会匹配。
需创建含“fred flintstone”相关内容的文本文件用于测试。
可使用正则表达式编写程序,示例代码如下:
while (<>) {
if (/fred/) {
print;
}
}
将上述代码保存为
.pl
文件,运行时将创建的文本文件作为输入,如:
perl script.pl input.txt
19、有一个程序,需要修改该程序,使其能匹配“Fred”。若输入字符串是“Fred”、“frederick”或“Alfred”,修改程序后能否匹配这几个字符串?(需将包含这些名字的行添加到文本文件中)
将程序的模式改为
/[fF]red/
,也可以尝试
/(f|F)red/
或
/fred|Fred/
,但字符类效率更高。修改后,输入“Fred”、“frederick”、“Alfred”都能匹配,因为:
“Fred”直接匹配
“frederick”和“Alfred”中包含“fred”
20、编写一个程序,打印出任何同时提及“wilma”和“fred”的输入行。
可通过正则表达式和条件判断来实现。思路是读取输入行,检查是否同时包含“wilma”和“fred”,若包含则打印该行。以下是一个 Python 示例代码:
while True:
try:
line = input()
if 'wilma' in line.lower() and 'fred' in line.lower():
print(line)
except EOFError:
break
21、创建一个模式,使其能匹配当前 $what 变量中内容的三个连续副本。也就是说,如果 $what 是 fred,你的模式应匹配 fredfredfred。如果 $what 是 fred|barney,你的模式应匹配 fredfredbarney、barneyfredfred、barneybarneybarney 等多种组合。(提示:你应该在模式测试程序的开头使用类似 my $what = ‘fred|barney’; 的语句来设置 $what。)
可以使用以下代码实现:
my $what = 'fred|barney';
while( <STDIN> ) {
chomp;
if ( /($what){3}/ ) {
print "Matches
";
} else {
print "Doesn't match
";
}
}
这里使用了括号将
$what
括起来,然后使用
{3}
量词来匹配其内容的三个连续副本。
22、编写一个程序,修改已有程序,使其不编辑已经包含版权行的文件。提示:由钻石操作符读取的文件名存储在 $ARGV 中。
为了避免重复添加版权信息,需要对文件进行两次遍历。首先,使用哈希创建一个“集合”,其中键是文件名,值可随意(为方便使用 1):
```perl
my %do_these;
foreach (@ARGV) {
$do_these{$_} = 1;
}
接着,检查文件并从待办列表中移除已经包含版权信息的文件。当前文件名存储在
$ARGV
中,可将其用作哈希键:
while (<>) {
if (/A## Copyright/) {
delete $do_these{$ARGV};
}
}
最后,在重新确定
@ARGV
中的文件名列表后,执行与之前相同的程序:
@ARGV = sort keys %do_these;
$^I = ".bak"; # 制作备份
exit unless @ARGV; # 没有参数则从标准输入读取!
while (<>) {
...
}
23、编写一个程序,该程序会不断让用户猜测一个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!
";
}
}