Perl编程实践:从基础到高级编程示例

内容分享2天前发布
0 0 0

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

”; 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;
© 版权声明

相关文章

暂无评论

none
暂无评论...