Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
324 lines (252 sloc) 12.1 KB

Perl入学式 #2

今日の流れ

  • 前回の復習
  • おまじない
  • 標準入力
  • 変数
  • 基本的な演算子
  • if, else文
  • for文, 配列

前回の復習

plenv

$ plenv versions
* 5.16.3
  system
  • plenv versionsとすることで, 5.16.3が選択されているか確認しよう
    • plenvのバージョンが古い方はplenv listで確認できます

Hello, World!

print "Hello, World!\n";
  • このように書いたものを, hello.plとして保存
  • printは, 端末に文字を出力する
  • \nは改行を表す
  • 最後に;を忘れずに

Hello, World! の実行

$ perl hello.pl
Hello, World!
  • perlの引数に実行するスクリプトファイル名を与えると, そのスクリプトを実行する

今日の内容

おまじない

#!/usr/bin/env perl
use strict;
use warnings;
  • おまじないとして, 冒頭の3行を書くようにしよう
  • use strict -> 厳密な書式を定めたり, 未定義の変数を警告するといった効果
  • use warnings -> 望ましくない記述を警告してくれる効果
    • 以下, この資料のサンプルコードでは「お約束」を省略します.
    • 書かれているものとして扱ってください.

use

use Acme::FizzBuzz;
  • useの後にモジュール名を書くことで, そのモジュールを読み込んで利用する事を意味する
  • 前回のAcme::FizzBuzzのように, CPANからモジュールを入手できる
    • インストール時にデフォルトで入っているモジュールもある

練習問題

  • 先程の冒頭の3行のおまじないを加えた上で, Hello, Worldという文字列を出力するhello.plを作成しよう

(スカラ)変数

my $hoge;
$hoge = 1;
my $foo = 3.14;
$hoge = "bar";
  • 変数の先頭には, $hogeのように$をつける
  • 変数を宣言するとき(最初に使うとき)は, 先頭にmy をつける
  • Perl では, C言語のように int, char といった型がないので, 数値や文字列などを自由に代入することができる

変数の出力

my $hoge = 1;
print "$hoge\n"; # 1
print '$hoge\n'; # $hoge\n
  • print を使うことで変数を出力することができる
  • 変数を出力する場合は, ""(ダブルクォテーション)の中に変数を書けばよい
    • ""の中に変数を書くと, その変数の中身が展開されて表示される
    • ''の中では, 展開はされず, 全てがそのまま出力される
  • \nは改行を意味する

練習問題

  • 自分の名前, 年齢, 身長などの情報をそれぞれname, age, heightといった変数に格納し, それらの値を出力するスクリプト profile.plを作成しよう
  • use strict, use warningsを使おう

標準入力

my $str = <STDIN>;
chomp $str;
print $str;
  • 端末からPerlに対して, 標準入力を介して文字列を入力することができる
    • <STDIN>で端末から入力し, 入力した文字列を変数strに格納する
    • chompにより行末の改行を削除できる
  • このスクリプトをstdin.plという名前で保存して, 実行してみよう

基本的な演算子(四則演算)

my $hoge = 4;
my $foo  = 2;
my $res;
$res = $hoge + $foo  # 4 + 2 = 6
$res = $hoge - $foo  # 4 - 2 = 2
$res = $hoge * $foo  # 4 * 2 = 8
$res = $hoge / $foo  # 4 / 2 = 2
$res = $hoge % $foo  # 4 % 2 = 0
$res = $hoge ** $foo # 4 の 2乗 は 16
  • perlでは, C言語と異なりべき乗の計算を簡単に行うことができる

基本的な演算子(文字列連結)

my $foo = 'hoge';
my $bar = 123;
my $baz = $foo . $bar; # hoge123
print $foo . $baz . "\n"; # hogehoge123
  • .で, 文字列や変数を結合することができます.

演算の順番

my $hoge = 2 + 4 * 3;   # 14
my $fuga = (2 + 4) * 3; # 18
  • 演算の順序は, ()を付けることで変更することができます.
    • 通常の数学と同じく, Perlも足し算・引き算より掛け算・割り算の優先順位が高いですが, 2行目は()を付けることで足し算を先に計算させています.

練習問題

  • 標準入力から変数を2つ読み込み, それらを四則演算(+, -, *, /)した結果を出力するスクリプト calc.plを作成しよう

制御構文(if)

my $hoge = 1;
if ( $hoge == 1 ) {
  print "OK\n"; # 条件が「真」の場合
} else {
  print "NG\n"; # 条件が「偽」の場合
}
  • == は"右辺と左辺が等しければ真"であることを意味する
    • 真 = 条件が正しい, 偽 = 条件が正しくない
  • ここでは$hoge1と等しい場合に限り真となり, OKという文字が表示される
  • $hogeが1でなければ, 偽となるためelseに処理が移りNGという文字が表示される

制御構文(if)

my $hoge = 1;
if ( $hoge == 1 ) {
  print "OK\n"; # 条件が「真」の場合
}
  • elseの部分は省略することもできる
    • この場合, 条件が偽の場合($hoge1ではない場合)は, 何の処理も行われない

数値の比較

== # 右辺と左辺が等しいならば真
!= # 右辺と左辺が等しくないならば真
<  # 右辺より左辺が小さいならば真
>  # 右辺より左辺が大きいならば真
<= # 右辺が左辺以上ならば真
>= # 右辺が左辺以下ならば真
  • 数字同士を比較するときは, このような比較演算子を使う

文字列の比較

eq  ==  equal
ne  !=  not equal
gt  >   greater than
ge  >=  greater equal
lt  <   less than
le  <=  less equal
  • 数値を比較する場合は==!=を使うが, 文字列を比較する場合はeqneといった演算子を使う
    • eq, ne以外はあまり使わない
    • 文字列の大小とは, 辞書順に並べた時に前にくるものが小さく, 後ろにくるものが大きいということ

文字列比較

my $hoge = 'hello';
if ( $hoge eq 'hello' ) {
    print "OK";
} else {
    print "NG";
}
  • 今回は文字列を比較しているので, ==ではなくeqを用いている
    • use warnings;が宣言されている状態で, 文字列に対して==を適用すると警告が発生する

練習問題

#!/usr/bin/env perl
use strict;
use warnings;
my $answer = 'perl'; # 好きな文字をいれる
  • 簡単な文字当てゲーム question_word.plを作成しよう
  • 端末から文字列を一つ入力し, その文字列が$answerと一致したらOK, 外れたらNGと表示する

複数の制御構文

my $hoge = 1;
if ( $hoge == 1 ) {
    ...
} elsif ( $hoge == 2 ) {
    ...
} elsif ( $hoge == 3 ) {
    ...
} else {
    ...
}
  • elsifを使うことで, 分岐条件をさらに増やすことができる.

関係演算子

&& -> かつ
|| -> または
  • if文で複雑な条件を扱いたいときは, 関係演算子を用いて複数の条件を連結するとよい.
    • &&演算子は「かつ」なので, 両方の条件が真となるときのみ真となる
    • ||演算子は「または」なので, 条件のどちらか1つでも真となるならば真となる

関係演算子

my $hoge = 64;
if ( $hoge > 0 && $hoge % 2 == 0 ) {
    print "&&: OK\n";
}
if ( $hoge > 0 || $hoge % 2 == 1 ) {
    print "||: OK\n";
}
  • 2行目は, 「64は0より大きい(真)」かつ「64を2で割った余りは0(真)」なので, 真となる
  • 5行目は, 「64は0より大きい(真)」または「64を2で割った余りは1(偽)」なので, 真となる

練習問題

#!/usr/bin/env perl
use strict;
use warnings;
my $answer = 1; # 好きな値をいれる
  • 簡単な数当てゲーム question_num.plを作成しよう
  • 端末から数字を一つ入力し, その数字が$answerと一致したらOK, $answerより大きければtoo big, 小さければtoo smallと表示する
    • オプション: 入力した値が, $answerから-5〜+5の範囲内($answerが10なら, 5〜15)の場合, nearと表示するようにしてみよう

配列

my @array = ( 1, "hoge", 3 );
print "@array\n";    # 1 hoge 3
print "$array[0]\n"; # 1
print "$array[1]\n"; # hoge
print "$array[2]\n"; # 3
  • 配列を使うことで, 数値や文字列をまとめて格納できます
  • 配列は変数名の前に@をつける
  • 配列の一つ一つの要素にアクセスする場合は$変数名[添字]を使う
    • 添字は1ではなく0からスタートして, 1ずつ増えていく

配列

my @array = ( 1, "hoge", 3 );
my $sum = $array[0] + $array[2];
print "$sum\n" # => 4
  • 配列の要素は普通のスカラ変数と同じように扱えるので, 代入や計算ができる

範囲演算子

my @array1 = ( 1, 2 );
my @array2 = ( 1 .. 5 );
my @array3 = ( @array1, 3 ); # (1, 2, 3)
  • ()を使うことで, 配列にをまとめて代入することができる
  • 連続する数字であれば, 範囲演算子..を使って1 .. 5と書くことで1以上10以下の値を配列に代入する
  • 3行目のように, 数値や文字列だけでなく, 配列も組み合わせることができる

reverse

my @array1 = ( 5, 4, 3, 2, 1 );
my @array2 = reverse ( 1 .. 5 ); # OK
my @array3 = ( 5 .. 1 ); # NG
  • @array1のように, 連番を逆の順番で配列に格納したい場合はreverseを使うとよい
    • 範囲演算子..は, 必ず右側の値が左側の値より大きくなければならないので, @array2 = ( 5 .. 1 );のように書くと@array2には空の要素が格納されるので注意

sort

my @array1 = ( 5, 4, 3, 2, 1 );
my @sorted = sort @array1; # (1, 2, 3, 4, 5)
  • sortを使うと, 配列の要素をソートしてくれる
    • sort { $a <=> $b }と書くと, 数値としてソート
    • sort { $a cmp $b }, あるいはsortのみを書くと, 文字列としてソート
  • 変数$a$bはsortで使う為に予約されているので, sort以外で使ってはいけない

for ループ

my @array = ( 1, "hoge", 3 );
for my $var ( @array ) {
  print "$var\n";
}
  • 配列の中身を走査するのに, for文がある
    • foreachと書いてもよい. Perlの内部では, 同じように処理される
  • この場合, 変数$var$array[0], $array[1] ... という値が順番に代入され, 処理が行われる

for ループ ( C言語風 )

my @array = ( 1, "hoge", 3 );
for ( my $i = 0; $i <= $#array; $i++ ) {
  print "$array[$i]\n";
}
  • $#arrayは, @arrayの最大の添字を表す -この場合, @arrayには3個の要素が格納されているので, 最大の添字は2となる
  • よほどの事がないかぎり, この方式のforは使いません!

for ループ

for my $i (1..10) {
    print "$i回目のhello!\n";
}
  • 「ある処理を10回繰り返したい」という場合, 範囲演算子を使ってこのように書くこともできる.
    • 結構便利なので覚えておこう!

練習問題

  • 配列@array<STDIN>を使って3つの文字列を格納し, これを「文字列として」ソートしたものを出力するsort.plを書いてみよう
    • ヒント: @arrayに文字列を3個入力する処理は, for文を使ってシンプルに書いてみよう

最終問題

  • FizzBuzz問題にチャレンジ!!
    • 1から100までの数字について, その数字が3で割り切れるならFizz, 5で割り切れるならBuzz, 3でも5でも割り切れるならFizzBuzz, それ以外ならばその数字自身を出力するfizzbuzz.plを作成しよう

復習問題

更新履歴

  • 2013/7/22: 加筆修正.