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、编写一个“Hello, world”程序并使其运行,可将程序命名为ex1 – 1。
以下是“Hello, world”程序示例:
#!/usr/bin/perl
print "Hello, world!
";
你可以将其保存为
ex1-1
。若在 Unix 系统上,还需使用以下命令使其可执行:
chmod a+x ex1-1
然后通过以下命令运行:
./ex1-1
2、运行以下程序,看看它会输出什么。你能看出它是如何改变命令输出的吗?程序内容为:print “Enter a string: “; $str =
; print “Enter a number of times: “; chomp($num =
); $result = $str x $num; print “The result is:$result”;
运行该程序后,它会提示用户输入一个字符串和一个数字。程序会将字符串重复指定的次数,并输出结果。该程序改变命令输出的方式在于它接收用户输入,并根据输入生成特定的输出,而不是直接输出固定的内容。
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、编写一个程序,提示并接受程序运行者输入的半径,然后计算并输出该半径对应的圆的周长。如果用户输入半径为12.5,程序应能正确计算出相应的圆周长。
以下是实现该功能的代码:
$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.
";
这段代码提示用户输入半径,读取输入并去除换行符,然后计算并输出圆的周长。如果用户输入
12.5
,将得到相应的圆周长结果。
5、编写一个程序,让用户输入圆的半径,若用户输入的半径小于零,程序报告的圆周长将为零,而不是负数。
可在计算圆周长的程序里添加条件判断,当用户输入的半径小于零时,直接将圆周长设为零。以下是示例代码(Python 语言):
import math
radius = float(input("请输入圆的半径: "))
if radius < 0:
circumference = 0
else:
circumference = 2 * math.pi * radius
print("圆的周长是: ", circumference)
6、编写一个程序,提示用户输入两个数字(分别在两行输入),并输出这两个数字的乘积。
以下是实现该功能的Perl代码:
print "Enter first number: ";
chomp($one = <STDIN>);
print "Enter second number: ";
chomp($two = <STDIN>);
$result = $one * $two;
print "The result is $result.";
上述代码中,首先提示用户输入第一个数字,使用
chomp
函数去除输入末尾的换行符后存储在变量
$one
中,接着提示用户输入第二个数字,同样去除换行符后存储在变量
$two
中,最后计算两数的乘积并存储在
$result
中,将结果输出。
7、编写一个程序,逐行读取一系列数字,直到输入结束,然后根据下面给出的人员姓名列表,为每个输入的数字打印对应的人员姓名。(将这个姓名列表硬编码到你的程序中,即它应该出现在程序的源代码里)。例如,如果输入的数字是 1、2、4 和 2,输出的姓名应该是 fred、betty、dino 和 betty。姓名列表为:fred betty barney dino wilma pebbles bamm – bamm
以下是一个Python实现的示例代码:
name_list = ['fred', 'betty', 'barney', 'dino', 'wilma', 'pebbles', 'bamm - bamm']
result = []
while True:
try:
num = int(input())
if 1 <= num <= len(name_list):
result.append(name_list[num - 1])
except (EOFError, ValueError):
break
print(', '.join(result))
这段代码首先定义了姓名列表,然后通过循环读取输入的数字,将对应姓名添加到结果列表中,直到输入结束,最后打印结果。
8、编写一个名为 total 的子程序,它返回一个数字列表的总和。该子程序不应执行任何输入/输出操作,只需处理其参数并将一个值返回给调用者。同时编写一个示例程序来测试这个子程序,验证它是否能正常工作。示例中第一组数字 1、3、5、7、9 的总和应该是 25。
以下是实现该功能的代码:
sub total {
my $sum = 0;
foreach (@_) {
$sum += $_;
}
return $sum;
}
这个子程序使用
$sum
来保存数字列表的总和。首先将
$sum
初始化为 0,然后通过
foreach
循环遍历参数列表,将每个参数加到
$sum
中,最后返回
$sum
。
9、编写一个程序来计算从 1 到 1000 的数字之和。
假设存在一个名为 total 的子程序用于计算数字序列的总和!
print "The numbers from 1 to 1000 add up to ", total(1..1000), ".
";
总和应该是
500500
。
10、附加题:编写一个名为
above_average
的子程序,它接受一个数字列表,并返回其中高于平均值(均值)的数字。(提示:编写另一个子程序,通过将总和除以项数来计算平均值。)在以下测试程序中测试你的子程序。`my @fred = above_average(1..10); print “@fred is @fred
above_average
”; 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(@_);
return $sum / $count;
}
sub above_average {
my $average = average(@_);
my @list;
foreach my $element (@_) {
if ($element > $average) {
push @list, $element;
}
}
return @list;
}
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_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;
}
12、修改之前的程序,让它告诉每个新到来的人之前已经迎接过的所有人的名字。执行以下语句序列: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:
"; # or Ctrl - Z
chomp(my @lines = <STDIN>);
print "1234567890" x 7, "12345
"; # 标尺线到第75列
foreach (@lines) {
printf "%20s
", $_;
}
程序说明:首先提示用户输入一些行,然后按Ctrl – D(在Windows上按Ctrl – Z)结束输入。接着读取所有行并去除行尾的换行符。之后打印标尺线,最后使用
foreach
循环遍历输入的每一行,使用
printf
以20字符右对齐的格式打印每一行。
14、编写一个程序,让用户可以选择列宽,当依次输入列宽、字符串(每行一个输入)时,字符串会显示在指定列宽的位置。例如依次输入30、hello、good – bye,字符串会显示在第30列。额外加分项:当选择的列宽较大时,让标尺行更长。
以下是实现该功能的Perl代码:
print "What column width would you like? ";
chomp(my $width = <STDIN>);
print "Enter some lines, then press Ctrl - D:
";
chomp(my @lines = <STDIN>);
print "1234567890" x (($width + 9)/10), "
";
foreach (@lines) {
printf "%${width}s
", $_;
}
代码解释:
首先提示用户输入列宽并存储在
$width
变量中,接着提示用户输入一些行并将这些行存储在
@lines
数组中。然后根据列宽
$width
生成标尺行。最后遍历
@lines
数组,使用
printf
函数按照用户指定的列宽右对齐输出每个字符串。
对于额外加分项,代码中通过
"1234567890" x (($width + 9)/10)
来生成标尺行,确保标尺行长度至少与所需长度一致。
15、编写一个程序,要求用户输入一个名字,并输出对应的姓氏。已知有以下名字和姓氏的对应关系:fred对应flintstone、barney对应rubble、wilma对应flintstone。
以下是实现该功能的程序示例:
my %last_name = qw{ fred flintstone barney rubble wilma flintstone };
print "Please enter a first name: ";
chomp(my $name = <STDIN>);
print "That's $name $last_name{$name}.
";
也可以这样分别赋值:
my %last_name;
$last_name{"fred"} = "flintstone";
$last_name{"barney"} = "rubble";
$last_name{"wilma"} = "flintstone";
注意,如果使用
my
声明哈希,必须在赋值元素之前声明哈希,不能只对变量的一部分使用
my
。同时,
chomp
函数很重要,要去除用户输入的换行符。
16、编写一个程序,打印输入中提到“fred”的每一行(对于其他行不做处理)。如果输入字符串是“Fred”、“frederick”或“Alfred”,是否能匹配?创建一个包含几行提及“fred flintstone”及其朋友的小文本文件,然后将该文件作为此程序的输入。
可使用正则表达式编写程序,示例代码如下(以Python为例):
with open('your_file.txt', 'r') as file:
for line in file:
if 'fred' in line.lower():
print(line.strip())
对于输入“Fred”、“frederick”或“Alfred”,“Fred”能匹配(若忽略大小写),“frederick”和“Alfred”不能匹配。需创建一个包含“fred flintstone”及其朋友相关内容的文本文件,文件名替换代码中的
your_file.txt
。
17、修改一个程序,使其也能匹配“Fred”。若输入字符串是“Fred”、“frederick”或“Alfred”,修改后的程序能否匹配到这些字符串?(需将包含这些名称的行添加到文本文件中)
可以将程序中使用的模式改为
/[fF]red/
,也可以尝试
/(f|F)red/
或
/fred|Fred/
,但字符类更高效。修改后能匹配
Fred
、
frederick
和
Alfred
,因为这些字符串都包含符合条件的内容。
18、编写一个程序,打印出每行中包含一个首字母大写但不是全大写的单词的行。该程序会匹配 Fred,但不匹配 fred 或 FRED 吗?
可以将模式改为
/[A-Z][a-z]+/
来实现该程序。该模式会匹配
Fred
,但不匹配
fred
或
FRED
,因为它要求单词首字母大写且后续字母为小写。
19、编写一个程序,打印出任何同时提及“wilma”和“fred”的输入行。
可使用正则表达式和编程语言来实现该程序。以 Python 为例,代码如下:
import re
while True:
try:
line = input()
if re.search(r'wilma', line, re.IGNORECASE) and re.search(r'fred', line, re.IGNORECASE):
print(line)
except EOFError:
break
上述代码会不断读取输入行,检查每行是否同时包含“wilma”和“fred”(不区分大小写),若包含则打印该行。当遇到文件结束符时停止程序。
20、使用模式测试程序,创建一个能匹配字符串“match”的模式。用输入字符串“beforematchafter”测试该程序。输出是否按正确顺序显示了匹配的三个部分?
有一种简单的方法可以实现,若输出未按预期显示为
“before<match>after”
,则可能采用了较复杂的方法。
21、使用模式测试程序,创建一个模式,用于匹配任何以字母 a 结尾的单词(这里的单词是指符合 w 定义的单词)。该模式是否能匹配 wilma 但不匹配 barney?它能否匹配字符串 ‘Mrs. Wilma Flintstone’ 中的单词?对于字符串 ‘wilma&fred’ 又如何呢?
可以使用模式 `/w*a/` 来匹配以字母 `a` 结尾的单词。它能匹配 `wilma` 但不匹配 `barney`,能匹配 `'Mrs. Wilma Flintstone'` 中的 `Wilma`,也能匹配 `'wilma&fred'` 中的 `wilma`。代码示例如下:
```perl
if (/(?<word>w*a)/) {
print "Matched: |$`<$&>$'|
";
print "'word' contains '$+{word}'
";
} else {
print "No match: |$_|
";
}
##22、创建一个模式,该模式能匹配$what当前所包含内容的三个连续副本。也就是说,如果$what是fred,你的模式应匹配fredfredfred。如果$what是fred|barney,你的模式应匹配fredfredbarney、barneyfredfred、barneybarneybarney或其他多种组合。(提示:你应该在模式测试程序的开头使用类似my $what = 'fred|barney';的语句来设置$what。)
可以使用`/^($what){3}$/`这个模式来匹配,示例代码如下:
```perl
my $what = 'fred|barney';
while (<>) {
if (/^($what){3}$/) {
print;
}
}
此代码会匹配包含
$what
内容三个连续副本的行。
23、编写一个程序,将如下版权声明行添加到所有练习答案文件中,即紧跟在“shebang”行之后添加一行类似这样的内容:## Copyright (C) 20XX by Yours Truly。需要对文件进行“原地”编辑,并保留备份。假设程序在调用时,待编辑的文件名已经在命令行中给出。
$^I = ".bak";
while (<>) {
if (/^#!/) {
$_ .= "## Copyright (C) 20XX by Yours Truly
";
}
print;
}
调用此程序时,需提供要更新的文件名,例如若练习文件名为
ex01 - 1
、
ex01 - 2
等,都以
ex...
开头,可使用:
./fix_my_copyright ex*
24、额外加分练习:修改上一个程序,使其不编辑已经包含版权声明行的文件。提示:由钻石操作符读取的文件名存储在 $ARGV 中。
为了避免给文件重复添加版权信息,需要对文件进行两次遍历。
首先,使用哈希创建一个“集合”,键为文件名,值可设为 1(为方便起见):
my %do_these;
foreach (@ARGV) {
$do_these{$_} = 1;
}
接着,检查文件,将已包含版权信息的文件从待处理列表中移除,当前文件名在
$ARGV
中,可将其作为哈希键。
25、编写一个程序,该程序会反复要求用户猜测一个1到100之间的秘密数字,直到用户猜对为止。程序应使用神奇公式 int(1 + rand 100) 随机选取数字。当用户猜错时,程序应回应“Too high”(太高)或“Too low”(太低)。如果用户输入“quit”或“exit”,或者输入空行,程序应退出。当然,如果用户猜对了,程序也应退出!
以下是实现该功能的程序:
my $secret = int(1 + rand 100);
# 这一行可在调试时取消注释
# print "Don't tell anyone, but the secret number is $secret.
";
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 small. Try again!
";
} elsif ($guess == $secret) {
print "That was it!
";
last;
} else {
print "Too large. Try again!
";
}
}
26、编写一个 Perl 程序,在运行过程中打印额外的调试信息,比如它选择的秘密数字(一个 1 到 100 之间的随机整数)。要使得可以关闭此调试信息,并且在关闭时程序不发出警告。如果你使用的是 Perl 5.10 或更高版本,使用 // 运算符;否则,使用条件运算符。
若使用 Perl 5.10 或更高版本:
use 5.010;
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;