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;
}
55、编写代码将命令行参数(UTF – 8编码)转换为对应的字符并打印
以下两种方式都可实现将命令行参数(UTF-8 编码)转换为对应的字符并打印:
方式一:
use utf8;
use Encode qw(encode decode);
my $string = decode('UTF-8', shift);
my $length = length($string);
$string = encode('UTF-8', $string);
print "$string has $length characters
";
方式二(使用
utf8::all
模块):
use utf8::all;
my $string = shift @ARGV;
my $length = length($string);
print "$string has $length characters
";
56、编写代码将命令行参数(UTF – 8编码)的每个字符转换为对应的Unicode码点并打印
可以使用以下Perl代码实现该功能:
#!/usr/bin/perl
use strict;
use warnings;
use Encode 'decode_utf8';
foreach my $arg (@ARGV) {
my $decoded = decode_utf8($arg);
foreach my $char (split //, $decoded) {
my $codepoint = ord($char);
print sprintf("U+%04X
", $codepoint);
}
}
将上述代码保存为一个
.pl
文件,比如
codepoint.pl
,然后在命令行运行
perl codepoint.pl 你的参数
即可将参数中每个字符转换为对应的Unicode码点并打印。
57、编写代码将命令行参数(UTF – 8编码)的每个字符转换为对应的Unicode码点并打印,要求码点格式为U+xxxx
以下是一个Perl代码示例,可将命令行参数(UTF-8编码)的每个字符转换为对应的Unicode码点并以
U+xxxx
格式打印:
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
foreach my $arg (@ARGV) {
foreach my $char (split //, $arg) {
my $codepoint = sprintf("U+%04X", ord($char));
print $codepoint, "
";
}
}
将上述代码保存为一个
.pl
文件,例如
unicode_converter.pl
,然后在命令行中运行:
perl unicode_converter.pl 你输入的参数
代码会将每个参数的字符转换为对应的Unicode码点并打印。
58、当添加 Convert::Distance::Metric 后,lib/ 目录的文件布局应该是怎样的?
lib/
└── Convert/
└── Distance/
├── Imperial.pm
└── Metric.pm
59、添加 Convert::Distance::Metric 后,查看 lib/ 目录文件布局以及更新 MANIFEST 文件内容,并说明具体情况
添加
Convert::Distance::Metric
后,
lib/
目录文件布局如下:
lib/
└── Convert/
└── Distance/
├── Imperial.pm
└── Metric.pm
更新后的
MANIFEST
文件内容如下:
Changes
lib/Convert/Distance/Imperial.pm
lib/Convert/Distance/Metric.pm
Makefile.PL
MANIFEST
README
t/00-load.t
t/manifest.t
t/pod-coverage.t
t/pod.t
60、编写一个程序,使用 Convert::Distance::Metric 模块进行公里和米的转换并输出结果
以下是一个满足需求的程序示例:
use Convert::Distance::Metric ":all";
# 把3.5公里转换为米
my $meters = kilometers_to_meters(3.5);
print "3.5公里等于 $meters 米
";
# 把转换后的米数再转换回公里
my $kilometers = meters_to_kilometers($meters);
print "$meters 米等于 $kilometers 公里
";
此程序借助
Convert::Distance::Metric
模块把3.5公里转换为米,接着再将结果转换回公里,最后输出转换结果。
61、编写一个名为 Person 的类,包含初始化、获取姓名、出生日期和年龄等方法
以下是实现该需求的代码:
package Person;
use strict;
use warnings;
use DateTime;
use Carp 'croak';
sub new {
my ( $class, $args ) = @_;
my $self = bless {} => $class;
$self->_initialize($args);
return $self;
}
sub _initialize {
my ( $self, $args ) = @_;
my %args = %$args;
my $name = delete $args{name};
my $birthdate = delete $args{birthdate};
unless ( $name && $name =~ /S/ ) {
croak "Person name must be supplied";
}
unless ( eval { $birthdate->isa('DateTime') } ) {
croak "Person birthdate must be a DateTime object";
}
$self->{name} = $name;
$self->{birthdate} = $birthdate;
}
sub name {
$_[0]->{name}
}
sub birthdate {
$_[0]->{birthdate}
}
sub age {
my $self = shift;
my $duration = DateTime->now - $self->birthdate;
return $duration->years;
}
1;
该代码定义了一个
Person
类,其中
new
方法用于创建对象,
_initialize
方法用于初始化对象属性,
name
方法用于获取姓名,
birthdate
方法用于获取出生日期,
age
方法用于计算并返回年龄。
62、请写出 Person 类的一种实现方式
以下是
Person
类的一种实现方式:
package Person;
use Moose;
has 'given_name' => (is => 'ro', required => 1);
has 'family_name' => (is => 'ro', required => 1);
has 'birthdate' => (is => 'ro', required => 1);
has 'title' => (is => 'rw');
sub name {
my $self = shift;
my $title = $self->title ? $self->title . ' ' : '';
return $title . $self->given_name . ' ' . $self->family_name;
}
sub age {
my $self = shift;
# 这里简单假设返回一个大于 100 的值,实际中应根据 birthdate 计算
return 101;
}
1;
此实现运用了 Moose 模块来定义类和属性,包含
given_name
、
family_name
、
birthdate
和
title
属性,还有
name
和
age
方法。
name
方法返回完整姓名,可包含头衔;
age
方法返回一个大于 100 的值,实际使用时应依据
birthdate
计算。
63、指出代码中存在的问题
文中提到两个代码相关问题:
正则表达式难以手动编写和调试;
Web应用未对用户提供的数据进行编码,导致页面可能出现安全问题。
64、请写出 Customer 类的实现方式
要实现 `Customer` 类,需先定义模式。假设顶级命名空间是 `Loki::`,可在 `lib/Loki/Schema.pm` 中定义模式,示例如下:
1. 定义 `Customer` 结果类:
```perl
package Loki::Schema::Result::Customer;
use base 'DBIx::Class::Core';
__PACKAGE__->table('customers');
__PACKAGE__->add_columns(
'id',
{
data_type => 'integer',
is_auto_increment => 1,
is_nullable => 0,
},
'first_name',
{
data_type => 'varchar',
size => 256,
is_nullable => 0,
},
'last_name',
{
data_type => 'varchar',
size => 256,
is_nullable => 0,
},
);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many('orders', 'Loki::Schema::Result::Order', 'customer_id');
```
2. 定义 `Order` 结果类:
```perl
package Loki::Schema::Result::Order;
use base 'DBIx::Class::Core';
__PACKAGE__->table('orders');
__PACKAGE__->add_columns(
'id',
{
data_type => 'integer',
is_auto_increment => 1,
is_nullable => 0,
},
'customer_id',
{
data_type => 'integer',
is_foreign_key => 1,
is_nullable => 0,
},
'total',
{
data_type => 'decimal',
size => [10, 2],
is_nullable => 0,
},
);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->belongs_to('customer', 'Loki::Schema::Result::Customer', 'customer_id');
```
3. 使用模式:
```perl
use Loki::Schema;
my $schema = Loki::Schema->connect($dsn, $user, $pass, %optional_attributes);
my $customer_rs = Loki::Schema::Result::Customer->resultset('Customer');
while ( my $customer = $customer_rs->next ) {
my $orders_rs = $customer->orders;
my $total = 0;
while ( my $order = $orders_rs->next ) {
$total += $order->total;
}
printf "Customer: %40s Total: %0.2f", $customer->full_name, $total;
}
```
</markdown>
##65、实现一个User类,包含username和password属性,对password进行MD5加密,并提供password_eq方法判断密码是否相等,同时可以测试该类。
以下是实现该功能的代码:
```perl
package User;
use Moose;
use Digest::MD5 'md5_hex';
use namespace::autoclean;
has username => (
is => 'ro',
isa => 'Str',
required => 1
);
has password => (
is => 'ro',
isa => 'Str',
writer => '_set_password',
);
sub BUILD {
my $self = shift;
$self->_set_password(md5_hex($self->password));
}
sub password_eq {
my ( $self, $password ) = @_;
$password = md5_hex($password);
return $password eq $self->password;
}
__PACKAGE__->meta->make_immutable;
1;
# 测试代码
my $user = User->new(
username => 'Ovid',
password => 'Corinna',
);
print $user->dump;
print "Yes" if $user->password_eq('Corinna');
上述代码定义了一个
User
类,包含
username
和
password
属性。在
BUILD
方法中,将
password
转换为 MD5 摘要。
password_eq
方法用于验证新密码是否与旧密码匹配。最后给出了测试该类的代码。
66、实现一个unique函数,返回列表中唯一元素,并按原列表顺序排列,同时进行测试
以下是使用Python实现的
unique
函数及其测试代码:
def unique(lst):
seen = set()
result = []
for item in lst:
if item not in seen:
result.append(item)
seen.add(item)
return result
# 测试代码
input_list = [3, 4, 1, 4, 7, 7, 4, 1, 3, 8]
output_list = unique(input_list)
print(output_list)
上述代码定义了
unique
函数,它接受一个列表作为输入,使用集合
seen
来记录已经出现过的元素,遍历列表时,若元素未出现过,则添加到结果列表中并更新集合。最后返回按原列表顺序排列的唯一元素列表,并进行了简单的测试。
67、修改 unique 函数,使其返回的唯一元素按顺序排列,并进行测试
以下是修改后的代码及测试:
use Test::Most;
sub unique {
my @array = @_;
my %seen;
my @unique;
foreach my $element (@array) {
push @unique, $element unless $seen{$element}++;
}
return @unique;
}
my @have = unique( 2, 3, 5, 4, 3, 5, 7 );
my @want = ( 2, 3, 5, 4, 7 );
is_deeply @have, @want, 'unique() should return unique() elements in order';
done_testing;
此代码中,
unique
函数会遍历输入数组并将未出现过的元素按顺序存入
@unique
数组,最后返回该数组。测试部分使用
is_deeply
函数比较
@have
和
@want
数组是否相等,以验证
unique
函数是否按顺序返回唯一元素。
68、请详细说明
Scalar::Util
模块中的
looks_like_number
函数,并给出使用示例
Scalar::Util
looks_like_number
`Scalar::Util`模块在Perl 5.7.3版本被纳入Perl核心,其中的`looks_like_number`函数可返回一个布尔值,用于判断一个字符串是否看起来像数字。
使用该函数前,需显式导入,示例如下:
```perl
use Scalar::Util 'looks_like_number';
使用示例:
my $is_number = looks_like_number('3fred');
此例中返回
false
;
my $is_number = looks_like_number('3e7');
此例中返回
true
。
在处理数据时,可利用该函数进行数据验证,如在
average
函数中,会遍历传入的参数,使用
looks_like_number
检查每个参数是否为数字,若不是则抛出错误。
sub average {
my @numbers = @_;
my $sum = 0;
foreach my $num (@numbers) {
die "$num is not a number" unless looks_like_number($num);
$sum += $num;
}
return $sum / @_;
}
69、在查看测试的 @want 数组时,研究 unique 函数,使其返回原始列表中按找到顺序排列的唯一元素。
可以将
unique
函数改写如下:
sub unique {
my @array = @_;
my %seen;
my @unique;
foreach my $element (@array) {
push @unique => $element unless $seen{$element}++;
}
return @unique;
}
此函数借助一个哈希表
%seen
来记录已出现的元素,遍历数组时,若元素未出现过,就将其添加到
@unique
数组里,从而保证返回的唯一元素按原始列表中的顺序排列。
70、原 unique 函数返回的元素顺序是哈希键的顺序,是随机的,如何让 unique 函数返回按顺序排列的唯一元素。
对返回的元素进行排序即可,使用相同的排序行为处理实际结果和预期结果数组,不必进行数值排序。
示例代码为:
is_deeply [ sort @have ], [ sort @want ], 'unique() 应按顺序返回唯一元素';
71、对于 reciprocal 函数的参数,如何判断其是否为合法数字以避免错误情况。
可使用 `Scalar::Util` 模块中的 `looks_like_number` 函数判断参数是否为数字。若不是数字,使用 `croak` 函数抛出错误信息,代码示例如下:
```perl
sub reciprocal {
my $number = shift;
unless ( looks_like_number($number) ) {
croak("Argument to reciprocal() must be a number");
}
unless ($number) {
croak("Illegal division by zero");
}
return 1 / $number;
}
##72、原 TestsFor::TV::Episode 中 %default_attributes 硬编码在测试方法中,如何重写 TestsFor::TV::Episode 以及编写 TestsFor::TV::Episode::Broadcast 的测试。
```markdown
重写 `TestsFor::TV::Episode` 时,将 `%default_attributes` 提取到单独的方法中。示例如下:
```perl
package TestsFor::TV::Episode;
use Test::Most;
sub default_attributes {
my $test = shift;
return (
series => 'Firefly',
director => 'Marita Grabiak',
title => 'Jaynestown',
genre => 'awesome',
season => 1,
episode_number => 7,
);
}
sub attributes {
my $test = shift;
my %default_attributes = $test->default_attributes;
my $class = $test->class_to_test;
my $episode = $class->new(%default_attributes);
while (my ($attribute, $value) = each %default_attributes) {
can_ok $episode, $attribute;
is $episode->$attribute, $value, "The value for '$attribute' should be correct";
}
my %attributes = %default_attributes;
foreach my $attribute (qw/season episode_number/) {
$attributes{$attribute} = 0;
throws_ok { $class->new(%attributes) } qr/Q($attribute) does not pass the type constraint/,
"Setting $attribute to less than zero should fail";
}
}
1;
编写
TestsFor::TV::Episode::Broadcast
的测试时,继承
TestsFor::TV::Episode
并扩展
default_attributes
方法添加
broadcast_date
属性,同时使用
Tests(+2)
声明额外的测试。示例如下:
package TestsFor::TV::Episode::Broadcast;
use Test::Most;
use DateTime;
use base 'TestsFor::TV::Episode';
sub default_attributes {
my $test = shift;
my %attributes = $test->SUPER::default_attributes;
$attributes{broadcast_date} = DateTime->new(
year => 2002,
month => 10,
day => 8,
);
return %attributes;
}
sub attributes : Tests(+2) {
my $test = shift;
$test->SUPER::attributes;
}
1;