gpt4 book ai didi

perl - 使用 perl 创建一个简单的计算器

转载 作者:行者123 更新时间:2023-12-02 09:12:27 25 4
gpt4 key购买 nike

我需要在 Perl 中设计一个简单的计算器,名为 ex1.pl,只有 + , - , * , 和 /职能。下面是我所拥有的。

while (@ARGV>0) {
if ($_=~m/(\d+)\s(.)\s(\d+)/) {
if ($2 == "+") {
print "$1 + $3\n";
}
elsif ($2 == "-") {
print "$1 - $3\n";
}
elsif ($2 == "*") {
print "$1 * $3\n";
}
elsif ($2 == "/") {
if ($3 == 0 ) {
print "$1 cannot be divided by 0\n";
}
else {
print "$1 / $3\n";
}
}
else {
print "operator not identified\n";
}
}
else {
print "syntax error\n";
}
}

例如,如果我输入 ./ex1.pl 5 + 2 , 它不断报告错误

在第 4 行的模式匹配 (m//) 中使用未初始化的值

直到我按 ctrl + c。谁能帮我找出我做错了什么?

最佳答案

循环 while(@ARGV>0)不分配给 $_正则表达式匹配完成,所以没有匹配,代码转到 else .另外,@ARGV永远不会被清空,所以代码处于无限循环中。

其余代码在语法上是正确的,但必须重写,因为它在编写正则表达式以处理整个输入时迭代输入中的单词。对于该正则表达式,处理需要依次接受每个参数,或者需要将命令行组装成一个字符串。

关于问题中代码的进一步评论将在下面进一步发布。

让我提供一个不同的方法

use warnings;
use strict;
use feature 'say';

use Scalar::Util qw(looks_like_number);

my ($n1, $op, $n2) = @ARGV;

my $re_oper = qr{^(?:\+|-|\*|/)$}; #/

usage() if @ARGV != 3
or not looks_like_number($n1) or not looks_like_number($n2)
or $op !~ $re_oper;

my %calculate = (
'+' => sub { return $_[0] + $_[1] },
'-' => sub { return $_[0] - $_[1] },
'*' => sub { return $_[0] * $_[1] },
'/' => sub {
die "Can't divide by zero" if $_[1] == 0;
return $_[0] / $_[1]
},
);

say $calculate{$op}->($n1, $n2);

sub usage {
say STDERR
"Usage: $0 number operator number\n",
"The \"operator\" is one of +,-,\\*,/\n",
"Note that multiplication (*) must be escaped at command line";
exit;
}

使用 looks_like_number 复制参数并检查错误。来自 Scalar::Util ,和一个正则表达式。我使用 qr operator 准备正则表达式模式以便单独指定,使测试、维护和扩展更容易。

然后我们定义一个带有匿名子例程作为值的散列(它们是代码引用,参见 4. in Making references in perlref ),通常称为 dispatch table .因此不需要级联 if-elsif series:对于给定的键(运算符),相应的值被取消引用,并且该子例程运行。

为简洁起见,参数在一个语句中进行检查,但最好逐个进行检查,以便能够向用户报告发生的确切错误(并引用导致错误的输入)。

关于已发布代码的更多细节
  • 操作符捕获的模式需要使用字符串比较进行测试,用 eq 做了什么?运营商,不与 == .看到这些 in perlop .
    所以if ($2 eq '+')
  • 默认情况下,正则表达式匹配是针对 $_ variable 完成的。 ,Perl 中许多东西的默认值。所以没有必要写if ($_ =~ /.../)但只是 if (/.../) .阅读什么证明(隐式)使用 $_ 的理由要清楚得多。
  • 正则表达式 \d匹配各种数字,包括 Unicode。更好用[0-9]
  • 图案\s允许一个“空白”字符。如果你通过 $input = join ' ', @ARGV; 将命令行参数组合成一个字符串(所以在它上面使用正则表达式)那很好。但是使用 \s+ 允许更多空间仍然更安全。 .
  • .在正则表达式中匹配任何一个字符。这限制了脚本 future 可能的扩展,例如提升到权力 ** (等等)。考虑允许数字之间的任何字符,这是可行的,因为它们在命令行上由空格分隔。
  • 用于数字的模式仅匹配正整数(如果前面有减号,则意外地允许第一个为负)。上面的代码通过使用 looks_like_number 来解决这个问题。 ,它利用 Perl 所能做的一切来识别一个数字。


  • 问题原版while (<>) for循环,答案是这样开始的:

    "diamond" operator ( <> )从命令行提交的文件中读取

    Input from <> comes either from standard input, or from each file listed on the command line.



    所以您的输入 5 + 2被视为文件名 5+2 ,而这样的文件不存在。

    这个操作符更复杂,可以在文档中阅读。

    命令行参数可以在 @ARGV 中访问,所以最简单的解决方案是更换 while (<>)foreach (@ARGV)然后逐项处理。

    关于perl - 使用 perl 创建一个简单的计算器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50597544/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com