Perl入学式2013年度第5回補講・参加レポート vol.5(whileなど)

おつかれさまです・・むっちゃ多忙です。が、精神の喜びを求めて更新してみます、Perl入学式レポートの続き。

前回の記事はこちらです。
Perl入学式2013年度第5回補講・参加レポート vol.4 - the code to rock

ええと、とりあえず前回までにどこまで来ていたかっていうと、この日(2013年度#5補講)の内容って大きく以下の2つなのですが、

  • 復習系: map, grep, whileなどこれまでの落穂ひろい
  • 新規系: Mojolicious導入, package, テストなどカリキュラム大詰めな感じ

今ちょうどその前者の終わりの方ですね。

ということで、今回はwhile, next, last, 後置if/forです。
https://github.com/perl-entrance-org/workshop-2013-05/blob/master/slide.md#while

と言いつつ、基本的には内容はもう上記のリンクを見て頂くとして、こちらの記事ではいつものとおり、練習問題に行ってしまいましょう。
まず僕の回答を書いて、その後papixさん(校長)の回答を並べたいと思います。
(長くなったら校長のぶんは次回に回しますが・・どうなるか)

では練習問題。

引数として与えられた文字列が, 数値A 演算子 数値Bという文字列であれば, その値を計算して, 結果を返すような関数calc_stringを書いてみましょう

  • 「数値A」は任意の桁の正・負の整数とします. また, 演算子は+-*/%が使えるものとします.
  • 但し, 引数が与えられなかった場合(空の文字列の場合)は, undefを返します
  • また, 数値A 演算子 数値Bというフォーマットと一致しない場合もundefを返します

関数calc_stringとwhile文を使って, Ctrlキーとdキーを押すまでの間標準入力から文字列を受け取り, 文字列に書かれた式を計算するようなコードを書いてみましょう

https://github.com/perl-entrance-org/workshop-2013-05/blob/master/slide.md#%E7%B7%B4%E7%BF%92%E5%95%8F%E9%A1%8C-1

はい。では私の回答、まず前者の方(while使う前まで)。

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

sub calc_string {
    my $str = shift;
    unless ($str =~ /^(-?\d+) (.) (-?\d+)$/) {
        return undef;
    } else {
        if ($2 eq '+') {
            return $1 + $3;
        } elsif ($2 eq '-') {
            return $1 - $3;
        } elsif ($2 eq '*') {
            return $1 * $3;
        } elsif ($2 eq '/') {
            return $1 / $3;
        } elsif ($2 eq '%') {
            return $1 % $3;
        }
    }
}

print calc_string('10 - 5')."\n";
print calc_string('-3 * 5')."\n";
print calc_string('hi * 5')."\n";

実行結果はこちら。

5
-15
Use of uninitialized value in concatenation (.) or string at calc_string.pl line 26.

ん、ん〜、最後のエラーの出方がなんか、ずばり「undef」と出てほしかったのですが、そんな感じでもないですね・・
でも以前にundef出したときは、この方法(return undef;)で行けたんだけど・・これの校長の回答とか。
http://note103.hateblo.jp/entry/2014/01/19/153450

これだったら普通に「ERROR!」とか出るほうがいいかな・・
ま、一旦続けます。

上記の内容に、whileと標準入力を取り入れろということで、こうなりました。

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

print "Input \'numeric operator numeric\'. For example, \'1 + 2\'\. \nIf finish, put <C-d>.\n";

while (my $input =<STDIN>) {
    print calc_string($input)."\n";
}

sub calc_string {
    my $str = shift;
    unless ($str =~ /^(-?\d+) (.) (-?\d+)$/) {
        return "Error! Please input \'numeric operator numeric\'. For example, \'1 + 2\'\.";
    } else {
        if ($2 eq '+') {
            return $1 + $3;
        } elsif ($2 eq '-') {
            return $1 - $3;
        } elsif ($2 eq '*') {
            return $1 * $3;
        } elsif ($2 eq '/') {
            return $1 / $3;
        } elsif ($2 eq '%') {
            return $1 % $3;
        }
    }
}

実行・・はこの形態だと掲載できないですが(対話型の内容なので)、まあ入力を促すところと、エラーの出方はちょっと工夫してみました。英語はめちゃくちゃですが・・

一応、手元ではいい感じに動いています。
ではこの続き、校長の解答を見ながらの答え合わせ編は次回にします!