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、当方括号内的数字2出现在练习题文本开头时,它意味着什么?
这个数字是对完成该特定练习题所需时间(分钟)的大致估计。
不过这只是粗略估算,实际完成时间可能是该数字的一半,也可能是两倍。
2、编写一个 Perl 程序,使其输出“Hello, world”并运行该程序,同时说明在命令行不创建文件运行该程序的方法。
程序代码如下:
print "Hello, world!
";
如果你使用的是 Perl 5.10 或更高版本,也可以尝试使用
say
:
use 5.010;
say "Hello, world!";
若想在命令行运行而不创建文件,可以使用
-e
开关指定程序:
$ perl -e 'print "Hello, World
"'
还有
-l
开关能自动添加换行符:
$ perl -le 'print "Hello, World"'
3、编写一个程序,计算半径为 12.5 的圆的周长。圆的周长是 2π乘以半径(约为 2 乘以 3.141592654)。
#!/usr/bin/perl -w
$pi = 3.141592654;
$circ = 2 * $pi * 12.5;
print "The circumference of a circle of radius 12.5 is $circ.
";
4、编写一个程序,提示用户输入圆的半径,然后计算并输出该圆的周长。如果用户输入的半径为负数,则周长按 0 处理。例如,当用户输入的半径为 12.5 时,程序应能正确计算并输出相应的周长。
#!/usr/bin/perl -w
$pi = 3.141592654;
print "What is the radius? ";
chomp($radius = <STDIN>);
$circ = 2 * $pi * $radius;
if ($radius < 0) {
$circ = 0;
}
print "The circumference of a circle of radius $radius is $circ.
";
5、编写一个程序,让用户输入一个圆的半径,若用户输入的数字小于零,程序报告的圆周长将为零,而不是负数。
#!/usr/bin/perl -w
$pi = 3.141592654;
print "What is the radius? ";
chomp($radius = <STDIN>);
$circ = 2 * $pi * $radius;
if ($radius < 0) {
$circ = 0;
}
print "The circumference of a circle of radius $radius is $circ.
";
6、编写一个程序,提示用户输入两个数字(在不同的输入行),并输出这两个数字相乘的结果。
以下是实现该功能的 Perl 代码示例:
print "请输入第一个数字: ";
chomp($num1 = <STDIN>);
print "请输入第二个数字: ";
chomp($num2 = <STDIN>);
$result = $num1 * $num2;
print "这两个数字的乘积是: $result
";
上述代码首先提示用户输入两个数字,使用
chomp
函数去除输入数字后的换行符,然后将这两个数字相乘得到结果,最后将结果输出。
7、编写一个程序,提示用户输入一个字符串和一个数字(分别在不同的输入行),并将该字符串按照数字指定的次数打印在不同的行上。(提示:使用 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
变量中。最后,程序打印出结果。注意,程序没有对输入的字符串进行
chomp
操作,这样可以确保每个重复的字符串都在单独的一行上。
8、编写一个程序,逐行读取一系列数字,直到输入结束,然后根据给定的姓名列表 [‘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])
else:
print('输入的数字超出范围')
except EOFError:
break
except ValueError:
print('输入不是有效的数字')
此代码先定义了姓名列表,接着在循环里读取输入的数字,将其转换为整数并检查是否在有效范围内,若有效则打印对应人名,同时处理了输入结束和输入非有效数字的情况。
9、编写一个名为 total 的子程序,它返回一个数字列表的总和。该子程序不应执行任何输入/输出操作,只需处理其参数并将一个值返回给调用者。请编写该子程序,并在示例程序中进行测试,示例程序如下:my @fred = qw{ 1 3 5 7 9 }; my $fred_total = total(@fred); print “The total of @fred is $fred_total.
”; print “Enter some numbers on separate lines: “; my $user_total = total(
); print “The total of those numbers is $user_total.
”;
以下是实现
total
子程序的代码:
sub total {
my $sum = 0;
foreach (@_) {
$sum += $_;
}
return $sum;
}
该子程序使用
$sum
来保存累加的总和,初始化为
0
。然后,
foreach
循环遍历参数列表(来自
@_
),使用
$_
作为控制变量,将每个元素累加到
$sum
中。最后返回
$sum
。这样即使参数列表为空,子程序也总是返回一个数字。
10、编写一个名为 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)
“;
以下是实现该功能的 Perl 代码:
sub total {
my $sum = 0;
foreach my $num (@_) {
$sum += $num;
}
return $sum;
}
sub average {
my @list = @_;
if (!@list) {
return undef;
}
my $sum = total(@list);
my $count = scalar @list;
return $sum / $count;
}
sub above_average {
my @list = @_;
my $average = average(@list);
my @result;
foreach my $element (@list) {
if ($element > $average) {
push @result, $element;
}
}
return @result;
}
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)
";
上述代码中,
total
子程序用于计算列表中所有数字的总和,
average
子程序通过调用
total
计算平均值,
above_average
子程序调用
average
并找出高于平均值的数字。
11、编写一个名为 greet 的子程序,当你传入人名时,该子程序会向此人表示欢迎,并告知其上次打招呼的人的名字。例如,执行 greet( “Fred” ); greet( “Barney” ); 这两条语句时,程序应输出:Hi Fred! You are the first one here! Hi Barney! Fred is also here!
以下是实现该功能的 Perl 代码:
use 5.010;
greet( 'Fred' );
greet( 'Barney' );
sub greet {
state $last_name;
my $name = shift;
print "Hi $name! ";
if( $last_name ) {
print "$last_name is also here!
";
} else {
print "You are the first one here!
";
}
$last_name = $name;
}
上述代码定义了一个
greet
子程序,使用
state
关键字声明了一个持久变量
$last_name
来存储上一次打招呼的人的名字。每次调用
greet
子程序时,会根据
$last_name
是否有值来输出不同的欢迎信息,并更新
$last_name
的值。
12、修改程序,使得每次调用
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
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 5.010;
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;
}
13、编写一个程序,要求用户在不同行输入一系列字符串,将每个字符串右对齐打印在一个20字符宽的列中。为确保输出列位置正确,同时打印一行数字作为“标尺线”(这只是一个调试辅助手段)。要确保不会误使用19字符宽的列!例如,输入hello、good – bye,输出应类似如下形式:123456789012345678901234567890123456789012345678901234567890
hello
good – bye
以下是实现该功能的示例代码:
print "Enter some lines, then press Ctrl - D:"; # 或 Ctrl - Z
chomp(my @lines = <STDIN>);
print "1234567890" x 6, "
"; # 打印标尺线
foreach (@lines) {
printf "%20s
", $_;
}
代码解释:首先提示用户输入一些行,按Ctrl – D(或Ctrl – Z)结束输入。使用
chomp
函数去除输入行末尾的换行符。然后打印标尺线,这里重复了6次“1234567890”。最后,使用
foreach
循环遍历输入的每一行,使用
printf
函数将每行右对齐打印在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
", $_;
}
该代码先让用户输入列宽,接着输入一些行,按Ctrl – D(或Ctrl – Z)结束输入。然后根据列宽生成合适的标尺线,最后将每行字符串按指定列宽右对齐输出。
15、编写一个程序,要求用户输入一个名字,并输出对应的姓氏。若输入的名字为 fred,输出 flintstone;若输入的名字为 barney,输出 rubble;若输入的名字为 wilma,输出 flintstone;若输入其他名字,输出未找到对应的姓氏。
以下是使用 Perl 语言实现该功能的代码:
use strict;
use warnings;
# 定义名字和姓氏的映射
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、编写一个程序,打印输入中提到“fred”的每一行(对于其他行不做处理)。如果输入字符串是“Fred”、“frederick”或“Alfred”,程序是否会匹配?创建一个包含几行提及“fred flintstone”及其朋友的小文本文件,然后将该文件作为此程序的输入。
要编写该程序,可将模式改为
/[fF]red/
。正则表达式区分大小写,原模式不匹配“Fred”,但新修改的模式可以。“frederick”和“Alfred”能匹配,因为它们都包含“fred”。
以下是示例代码:
while (<>) {
if (/[fF]red/) {
print;
}
}
将上述代码保存为一个 Perl 文件(如
print_fred_lines.pl
),并创建一个包含“fred flintstone”及其朋友的文本文件(如
friends.txt
),然后在命令行运行:
perl print_fred_lines.pl friends.txt
17、修改之前的程序,使其也能匹配 Fred。若输入字符串是 Fred、frederick 或 Alfred,修改后的程序能否匹配这些字符串 ?(可将这些名字添加到文本文件中进行测试)
可以将之前程序使用的模式修改为
/[fF]red/
,也可以尝试
/(f|F)red/
或
/fred|Fred/
,但字符类更高效。
正则表达式区分大小写:
不匹配
Fred
能匹配
frederick
和
Alfred
,因为这两个字符串都包含四个字母的字符串
fred
仅匹配整个单词,使
frederick
和
Alfred
不匹配,这是后续会介绍的功能。
18、编写一个程序,打印出每行中包含一个首字母大写但并非全大写单词的行。该程序是否能匹配“Fred”,而不匹配“fred”和“FRED”?
可以通过将模式更改为
/[A-Z][a-z]+/
来实现此程序。该模式能匹配像“Fred”这样首字母大写且后续字母小写的单词,而不匹配全小写的“fred”和全大写的“FRED”。
19、使用模式测试程序,创建一个模式,用于匹配任何以字母 a 结尾的单词(这里的单词是指符合 w 定义的单词)。该模式是否能匹配 wilma 但不匹配 barney?是否能匹配 Mrs. Wilma Flintstone?wilma&fred 呢?
可使用模式
/w*a/
来匹配以字母
a
结尾的单词。
此模式能匹配
wilma
但不匹配
barney
,能匹配
Mrs. Wilma Flintstone
以及
wilma&fred
。
20、创建一个模式,该模式能匹配当前 $what 变量中内容的三个连续副本。也就是说,如果 $what 的值是 fred,你的模式应能匹配 fredfredfred。如果 $what 的值是 fred|barney,你的模式应能匹配 fredfredbarney、barneyfredfred、barneybarneybarney 或其他多种组合。(提示:你应该在模式测试程序的开头使用类似 my $what = ‘fred|barney’; 的语句来设置 $what。)
可以使用如下模式来实现:
qr/(?:$what){3}/
。
解释:
(?:$what)
是一个非捕获组,它将
$what
的内容作为一个整体;
{3}
表示前面的非捕获组要连续出现 3 次。
在 Perl 代码中可以这样使用:
my $what = 'fred|barney';
my $pattern = qr/(?:$what){3}/;
然后使用该模式进行匹配操作。
21、修改上一个程序,将每个 Fred 替换为 Wilma,将每个 Wilma 替换为 Fred。现在,像 fred&wilma 这样的输入在输出中应变为 Wilma&Fred。
以下是一个实现该功能的 Perl 程序示例:
#!/usr/bin/perl
use strict;
use warnings;
# 检查是否提供了输入文件名
if (@ARGV != 1) {
die "Usage: $0 <input_file>";
}
my $input_file = $ARGV[0];
my $output_file = $input_file . ".out";
open(my $in_fh, '<', $input_file) or die "Can't open $input_file: $!";
open(my $out_fh, '>', $output_file) or die "Can't open $output_file: $!";
while (my $line = <$in_fh>) {
# 先将 Fred 替换为临时字符串,避免后续替换时产生冲突
$line =~ s/(?i)Fred/TEMP_FRED/g;
# 将 Wilma 替换为 Fred
$line =~ s/(?i)Wilma/Fred/g;
# 将临时字符串替换为 Wilma
$line =~ s/TEMP_FRED/Wilma/g;
print $out_fh $line;
}
close($in_fh);
close($out_fh);
将上述代码保存为一个 Perl 文件(例如
replace_names.pl
),然后在命令行中运行:
perl replace_names.pl your_input_file.txt
程序会读取输入文件,将其中的 Fred 和 Wilma 进行互换,并将结果保存到以
.out
结尾的输出文件中。
22、修改一个程序,使其不编辑已经包含版权声明行的文件。提示:由钻石操作符读取的文件名存储在 $ARGV 中。
以下是修改后的程序:
首先创建一个哈希
%do_these
,将命令行参数作为键存入,值设为
1
。接着遍历文件,若文件中包含以
## Copyright
开头的行,则从
%do_these
中删除该文件名对应的键。最后将
%do_these
中的键排序后重新赋值给
@ARGV
,再进行版权声明添加操作。
代码如下:
my %do_these;
foreach (@ARGV) {
$do_these{$_} = 1;
}
while (<>) {
if (/^## Copyright/) {
delete $do_these{$ARGV};
}
}
@ARGV = sort keys %do_these;
$^I = ".bak";
while (<>) {
if (/^#!/) {
$_ .= "## Copyright (c) 20XX by Yours Truly
";
}
print;
}
23、编写一个程序,该程序重复要求用户猜测一个1到100之间的秘密数字,直到用户猜对为止。程序应使用神奇公式 int(1 + rand 100) 随机选取数字。当用户猜错时,程序应回应“Too high”或“Too low”。如果用户输入“quit”或“exit”,或者输入空行,程序应退出。当然,如果用户猜对了,程序也应退出。
以下是一个满足需求的Perl程序示例:
use 5.010;
my $secret = int(1 + rand 100);
while (1) {
print "Please enter a guess from 1 to 100 (or 'quit'/'exit' to quit): ";
chomp(my $guess = <STDIN>);
if ($guess eq 'quit' || $guess eq 'exit' || $guess eq '') {
last;
}
if ($guess =~ /^d+$/) {
if ($guess == $secret) {
print "Correct! You guessed the secret number.";
last;
} elsif ($guess > $secret) {
print "Too high
";
} else {
print "Too low
";
}
} else {
print "Invalid input. Please enter a valid number or 'quit'/'exit'.
";
}
}
这个程序首先使用
int(1 + rand 100)
生成一个1到100之间的随机数作为秘密数字。然后进入一个无限循环,不断要求用户输入猜测的数字。如果用户输入“quit”、“exit”或空行,程序将退出循环。如果用户输入的是有效的数字,程序会将其与秘密数字进行比较,并给出“Too high”或“Too low”的提示,直到用户猜对或选择退出。