Perl与Python编程实践技巧合集

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;
}

48、编写代码实现:有一个包含名字的数组 @names = qw/ fred betty barney dino wilma pebbles bamm – bamm /,提示用户输入 1 到 7 的数字,每行一个,按 Ctrl – D 结束,根据用户输入的数字输出对应名字。

以下是实现该功能的 Perl 代码:


#!/usr/bin/perl
use strict;
use warnings;

# 定义名字数组
my @names = qw/ fred betty barney dino wilma pebbles bamm-bamm /;

# 提示用户输入
print "请输入 1 到 7 的数字,每行一个,按 Ctrl-D 结束:
";

while (my $input = <STDIN>) {
    chomp $input;
    if ($input =~ /^[1-7]$/) {
        my $index = $input - 1;
        print $names[$index], "
";
    } else {
        print "输入无效,请输入 1 到 7 的数字。
";
    }
}

上述代码首先定义了名字数组

@names

,然后提示用户输入 1 到 7 的数字。在循环中,读取用户输入,去除换行符,检查输入是否为 1 到 7 的数字。如果是,则输出对应名字;否则,提示输入无效。按 Ctrl-D 结束输入。

49、编写代码实现:对用户输入的行进行排序并输出,分别实现输出在一行和分行输出两种情况。

以下是使用Python语言实现的代码示例:


# 获取用户输入的行
lines = []
while True:
    line = input('请输入行内容(输入空行结束):')
    if not line:
        break
    lines.append(line)

# 对输入的行进行排序
sorted_lines = sorted(lines)

# 输出在一行
print('一行输出:', ' '.join(sorted_lines))

# 分行输出
print('分行输出:')
for line in sorted_lines:
    print(line)

上述代码首先通过循环获取用户输入的行,直到用户输入空行结束。接着对输入的行进行排序,然后分别实现了将排序后的行输出在一行和分行输出的功能。

50、编写一个名为 total 的子例程,用于计算传入参数的总和。

以下是编写名为

total

的子例程的代码:


sub total {
    my $sum = 0;
    foreach my $num (@_) {
        $sum += $num;
    }
    return $sum;
}

此子例程接收一个数字列表作为参数,通过遍历该列表将每个数字累加到变量

$sum

中,最后返回总和。

51、使用子程序计算1到1000的数字总和并打印结果。

可以使用

List::Util

模块中的

sum

函数来计算 1 到 1000 的数字总和,示例代码如下:


use List::Util qw(sum);
my $total = sum( 1..1000 );
print $total; # 输出 500500

52、编写子程序average来计算参数列表的平均值,编写子程序above_average来返回参数列表中大于平均值的所有元素。

以下是实现这两个子程序的Perl代码示例:


sub average {
    my $total = 0;
    foreach my $num (@_) {
        $total += $num;
    }
    return $total / scalar @_;
}

sub above_average {
    my $avg = average(@_);
    my @result;
    foreach my $num (@_) {
        if ($num > $avg) {
            push @result, $num;
        }
    }
    return @result;
}

在上述代码中,

average

子程序通过遍历传入的参数列表,累加所有元素的值,然后除以元素的数量得到平均值。

above_average

子程序先调用

average

子程序计算平均值,然后遍历参数列表,将大于平均值的元素添加到结果数组中并返回。

53、编写一个子程序greet,使用状态变量记住最后一个打招呼的人,并根据情况输出不同的问候语。

以下是实现该功能的代码:


use v5.10;

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;
}

54、编写一个子程序greet,使用状态变量存储所有见过的人的名字,并根据情况输出不同的问候语。当有新的人被问候时,如果之前没有见过任何人,输出‘You are the first one here!’;如果之前见过其他人,输出之前见过的所有人的名字。

以下是修改后的代码:


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;
}

这段代码定义了一个子程序

greet

,使用状态变量

@names

存储所有见过的人的名字。当有新的人被问候时,如果

@names

为空,说明这是第一个人,输出‘You are the first one here!’;如果

@names

不为空,输出之前见过的所有人的名字。最后,将新问候的人的名字添加到

@names

数组中。

55、编写一个程序,使用reverse函数和钻石操作符逆序打印用户选择的文件的所有行。

以下是一个满足需求的Perl程序示例:


#!/usr/bin/perl
use strict;
use warnings;

my @lines = <STDIN>;
@lines = reverse @lines;
print @lines;

在命令行中运行该程序时,可通过重定向将文件内容作为标准输入,例如:

perl your_script.pl < your_file.txt

程序会逆序打印文件的所有行。

56、编写一个程序,读取用户输入的多行文本,去掉每行末尾的换行符,然后以20个字符的宽度右对齐打印这些行。

以下是一个满足需求的Perl程序示例:


while (<>) {
    chomp;
    printf "%20s
", $_;
}

该程序使用

while (<>)

循环逐行读取用户输入,

chomp

函数去掉每行末尾的换行符,

printf

函数以20个字符的宽度右对齐打印每行内容。

57、编写一个程序,使用

print


reverse

以及钻石操作符

<>

实现将用户选择的所有文件的行反转输出

print reverse <>;

58、编写一个程序,先提示用户输入列宽,再提示用户输入一些行,然后将这些行以用户指定的列宽右对齐输出,并输出合适的标尺行

以下是一个满足需求的 Perl 程序示例:


#!/usr/bin/perl
use strict;
use warnings;

# 提示用户输入列宽
print "请输入列宽: ";
my $width = <STDIN>;
chomp($width);

# 提示用户输入一些行
print "请输入一些行,输入空行结束输入:";
my @lines;
while (my $line = <STDIN>) {
    chomp($line);
    last if $line eq '';
    push @lines, $line;
}

# 输出标尺行
my $ruler = '';
for (my $i = 1; $i <= $width; $i++) {
    $ruler .= ($i % 10 == 0) ? int($i / 10) : ' ';
}
print $ruler, "
";

# 输出右对齐的行
foreach my $line (@lines) {
    printf "%*s
", $width, $line;
}

这个程序首先提示用户输入列宽,接着提示用户输入一些行,输入空行时结束输入。然后程序会生成一个合适的标尺行并输出,最后将用户输入的行以指定列宽右对齐输出。

59、编写程序,从用户输入中获取名字,在哈希表中查找对应的姓氏并输出,同时考虑输入的健壮性,可添加检查键是否存在的功能

以下是一个使用 Python 实现的示例代码:


# 定义哈希表
name_dict = { 
    "小明": "张", 
    "小红": "李", 
    "小刚": "王"
}

# 获取用户输入
name = input("请输入名字:")

# 检查键是否存在
if name in name_dict:
    print(f"{name} 的姓氏是 {name_dict[name]}")
else:
    print(f"未找到 {name} 的姓氏信息")

这段代码首先定义了一个包含名字和对应姓氏的哈希表(在 Python 中是字典),然后获取用户输入的名字,接着检查该名字是否在字典中,如果存在则输出对应的姓氏,不存在则给出提示。

60、编写程序,从标准输入读取单词,统计每个单词出现的次数并输出,可考虑对输出的单词进行排序

以下是使用 Python 实现的代码示例:


word_count = {}
# 从标准输入读取单词,直到遇到 EOF(在 Windows 上按 Ctrl+Z 然后按 Enter,在 Linux/Mac 上按 Ctrl+D)
while True:
    try:
        line = input()
        words = line.split()
        for word in words:
            if word in word_count:
                word_count[word] += 1
            else:
                word_count[word] = 1
    except EOFError:
        break

# 对单词进行排序并输出结果
sorted_words = sorted(word_count.items())
for word, count in sorted_words:
    print(f'{word}: {count}')

上述代码首先创建一个空字典用于存储单词及其出现次数,接着从标准输入读取每一行并分割成单词,统计每个单词出现的次数。最后对字典中的单词进行排序并输出结果。

61、编写代码来找出输入中包含 ‘fred’ 的行。


while( <STDIN> ) {
    chomp;
    if ( /fred/ ) {
        print;
    }
}

62、编写一个正则表达式模式,使其能匹配 ‘fred’ 或 ‘Fred’。

可将模式改为

/[fF]red/

,也可以尝试

/(f|F)red/


/fred|Fred/

,不过字符类

/[fF]red/

效率更高。

63、修改第一题的模式,使其匹配点号(.)。

在正则表达式中,点号(

.

)有特殊含义,若要匹配点号本身,需使用反斜杠转义,即

.

。例如原本模式是

abc

,若要匹配

abc.

,则修改后的模式为

abc.

64、修改一个模式,使其匹配以大写字母开头,后面跟一个或多个小写字母的单词。

可以使用正则表达式来实现这个匹配模式。在大多数编程语言中,对应的正则表达式为

[A-Z][a-z]+$

。以下以 Python 为例展示如何使用这个正则表达式进行匹配:


import re

pattern = re.compile(r'^[A-Z][a-z]+$')
# 测试字符串
test_string = 'Apple'
if pattern.match(test_string):
    print(f'{test_string} 匹配成功')
else:
    print(f'{test_string} 匹配失败')

上述代码中,

^

表示字符串的开始,

[A-Z]

匹配一个大写字母,

[a-z]+

匹配一个或多个小写字母,

$

表示字符串的结束。

65、编写代码来找出同时包含 ‘wilma’ 和 ‘fred’ 的行。

以下几种方式可以实现找出同时包含 ‘wilma’ 和 ‘fred’ 的行:

方式一:


while (<>) {
    if (/wilma/) {
        if (/fred/) {
            print;
        }
    }
}

方式二:


while (<>) {
    if (/wilma.*fred|fred.*wilma/) {
        print;
    }
}

方式三(使用逻辑与运算符):


while (<>) {
    if (/wilma/ && /fred/) {
        print;
    }
}

66、编写一个正则表达式,用于匹配以字母 ‘a’ 结尾的单词,后面跟随最多五个字符,并编写代码显示捕获的最多五个字符的部分。

正则表达式可写成

/$(w*a)(.{0,5})/

,其中:

第一个捕获组

(w*a)

匹配以

'a'

结尾的单词

第二个捕获组

(.{0,5})

匹配最多五个字符

以下是示例代码:


my $input = 'I saw Wilma yesterday';
if ($input =~ /(w*a)(.{0,5})/) {
    print "Up - to - five characters after the word ending with 'a': '$2'
";
}

67、编写一个正则表达式模式,用于匹配某个模式($what)重复三次的序列,并解释括号的必要性。

正则表达式模式可以写成

/($what){3}/

。括号的必要性在于,它用于将

$what

模式进行分组,确保是

$what

这个整体重复三次,而不是

$what

中的部分字符或元素分别重复。如果没有括号,量词

{3}

可能会错误地应用到

$what

的某个部分,导致匹配结果不符合预期。

68、编写一个程序,从文件句柄 $in_fh 读取内容,将所有的 ‘Fred’ 替换为换行符,所有的 ‘Wilma’ 替换为 ‘Fred’,然后将换行符替换为 ‘Wilma’。

以下是实现该功能的程序代码:


while (<$in_fh>) {
    chomp;
    s/Fred//gi;
    s/Wilma/Fred/gi;
    s//Wilma/g;
    print;
}

原答案只是进行了替换操作,但没有将处理后的内容输出,添加

print;

语句用于输出处理后的内容。

69、编写一个模式来匹配某个变量 $what 重复三次的字符串。解释为什么需要使用括号。

模式可以写成

/($what){3}/



使用括号是为了将

$what

作为一个整体进行处理,确保是整个

$what

重复三次,而不是仅

$what

中的部分字符重复三次。

如果不使用括号,可能无法正确匹配到想要的结果。

70、修改一个程序,将文件中的 ‘Fred’ 和 ‘Wilma’ 互换。解释为何需要占位符字符串以及如何选择它。

要将文件中的

Fred


Wilma

互换,若直接进行替换,会出现问题。例如,先把

Fred

替换成

Wilma

,再把

Wilma

替换成

Fred

,会导致最终所有内容都变成

Fred

所以需要占位符字符串,先把其中一个词替换成占位符,再把另一个词替换过去,最后把占位符替换为剩下的词。

选择占位符时,要确保它不会在文件中自然出现。可以使用一个非常独特、不太可能在文本里出现的字符串,如一串随机字符

xyz123abc

等。

71、编写一个Perl程序,将版权声明 ‘## Copyright (C) 20XX by Yours Truly’ 添加到所有给定文件的Shebang行末尾,并对原始文件进行备份。

以下是相应的Perl程序:


$^I = ".bak"; # 进行备份
while (<>) { 
    if (/^#!/) { # 判断是否为Shebang行 
        $_ .= "## Copyright (C) 20XX by Yours Truly
"; 
    } 
    print;
}

使用时,在命令行输入类似

./fix_my_copyright ex*

的命令,其中

ex*

是你要更新的文件名。

72、编写一个Perl程序,生成一个1到100之间的随机数,并允许用户猜测该数字。用户可以输入’quit’或’exit’来停止游戏。根据用户的猜测给出相应的反馈。

以下是满足需求的Perl程序:


my $secret = int(1 + rand 100);
# This next line may be un - commented during debugging
# 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!
";
    }
}

该程序首先生成一个1到100之间的随机数作为秘密数字。然后进入一个无限循环,不断提示用户输入猜测的数字。如果用户输入

quit


exit

或空白行,程序会告知用户放弃游戏并公布秘密数字后退出循环;如果猜测的数字小于秘密数字,程序提示

Too small. Try again!

;如果猜测正确,程序提示

That was it!

并退出循环;如果猜测的数字大于秘密数字,程序提示

Too large. Try again!

73、编写一个程序,从 1 到 100 中随机选择一个秘密数字,让用户猜测该数字,直到猜对或用户输入 quit、exit 或空白退出,并解释程序中随机数生成部分的工作原理以及为什么要先测试可能的字符串再测试数字。


import random
# 生成 1 到 100 之间的随机数
secret_number = random.randint(1, 100)
while True:
    guess = input("请输入你的猜测(输入 quit、exit 或直接回车可退出): ")
    if guess.lower() in ['quit', 'exit', '']:
        print("退出游戏。")
        break
    try:
        guess = int(guess)
        if guess == secret_number:
            print("恭喜你,猜对了!")
            break
        elif guess < secret_number:
            print("猜的数字太小了,再试试。")
        else:
            print("猜的数字太大了,再试试。")
    except ValueError:
        print("输入无效,请输入一个有效的数字。")

随机数生成部分工作原理

在 Python 中,

random.randint(a, b)

函数用于生成一个指定范围内的整数。

a

是范围的下限,

b

是范围的上限,生成的随机整数

n

满足

a <= n <= b

。在这个程序里,

random.randint(1, 100)

会从 1 到 100 这个闭区间内随机选取一个整数作为秘密数字。

先测试可能的字符串再测试数字的原因

先测试可能的字符串(如 ‘quit’、’exit’ 或空白)是为了让用户能够顺利退出游戏。如果先测试数字,当用户输入退出指令时,程序会尝试将这些字符串转换为数字,从而引发

ValueError

异常,无法正常退出游戏。先检查退出指令可以让程序优先处理用户的退出意图,提供更好的用户体验。

© 版权声明

相关文章

暂无评论

none
暂无评论...