blog/content/post/2008-02-06-『新版perl言語プログラミング...

254 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: '『新版Perl言語プログラミングレッスン入門編』第6章: 繰り返し'
author: kazu634
date: 2008-02-06
url: /2008/02/06/_839/
wordtwit_post_info:
- 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:3691;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}'
categories:
- Perl
- Programming
---
<div class="section">
<p>
 繰り返しについて勉強するよー
</p>
<p>
<a name="seemore"></a>
</p>
<h4>
foreach構文
</h4>
<p>
 これまで何度も出てきた構文。変数の中にリストの値を順番に格納する構文だよ。基本構造は
</p>
<pre class="syntax-highlight">
<span class="synStatement">foreach</span> <span class="synStatement">my</span> 変数 (リスト) {
処理
}
</pre>
<p>
というようになる。「my 変数」は省略可能で、処理の中で「$_」と表記できる。例はこんな感じ:
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">my</span> <span class="synIdentifier">@name</span> = (<span class="synConstant">'Musashi'</span>, <span class="synConstant">'Aiko'</span>, <span class="synConstant">'Nanbu'</span>);
<span class="synStatement">foreach</span> (<span class="synIdentifier">@name</span>) {
<span class="synStatement">print</span> <span class="synConstant">&#34;</span><span class="synIdentifier">$_</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>;
}
</pre>
<p>
リストの値でソートさせて表示させたいときにはこのようにする。
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">my</span> <span class="synIdentifier">@name</span> = (<span class="synConstant">'Musashi'</span>, <span class="synConstant">'Aiko'</span>, <span class="synConstant">'Nanbu'</span>);
<span class="synStatement">foreach</span> (<span class="synStatement">sort</span>(<span class="synIdentifier">@name</span>)) {
<span class="synStatement">print</span> <span class="synConstant">&#34;</span><span class="synIdentifier">$_</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>;
}
</pre>
<p>
逆順にソートするときは「reverse(sort(@name))」とすればいい。reverseは「リストの内容を単純に逆にするだけ」ということに注意。だから「reverse(@name)」は
</p>
<ol>
<li>
Nanbu
</li>
<li>
Aiko
</li>
<li>
Musashi
</li>
</ol>
<p>
という結果になるよ当たり前だけど、foreachを二重orそれ以上にすることもできる。例としてはこんなのが載っていた:
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">my</span> <span class="synIdentifier">@data</span> = (
<span class="synConstant">&#34;Musashi, 70, 83, 41&#34;</span>,
<span class="synConstant">&#34;Aiko, 90, 70, 50&#34;</span>,
<span class="synConstant">&#34;Nanbu,100, 30, 20&#34;</span>,
);
<span class="synStatement">foreach</span> (<span class="synIdentifier">@data</span>) {
<span class="synStatement">my</span> (<span class="synIdentifier">$name</span>, <span class="synIdentifier">@score</span>) = <span class="synStatement">split</span>(<span class="synStatement">/</span><span class="synConstant">,</span><span class="synStatement">/</span>, <span class="synIdentifier">$_</span>);
<span class="synStatement">my</span> <span class="synIdentifier">$sum</span> = <span class="synConstant"></span>;
<span class="synStatement">foreach</span> (<span class="synIdentifier">@score</span>) {
<span class="synIdentifier">$sum</span> += <span class="synIdentifier">$_</span>;
}
<span class="synStatement">print</span> <span class="synConstant">&#34;</span><span class="synIdentifier">$name</span><span class="synConstant">: </span><span class="synIdentifier">$sum</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>;
}
</pre>
<p>
自分としては「my ($name, @score) = split(/,/, $_);」がファジーすぎると感じる。説明によれば、
</p>
<blockquote>
<p>
split(/,/, $line)は、$lineの文字列をコンマで区切り、そのそれぞれの要素をまとめたリストを作ります。例えば、$lineの値が
</p>
<pre class="syntax-highlight">
<span class="synConstant">'Hiroshi Yuki, 70, 83, 41'</span>
</pre>
<p>
だとすると、split(/,/, $line)の値は、
</p>
<pre class="syntax-highlight">
(<span class="synConstant">'Hiroshi Yuki'</span>, <span class="synConstant">'70'</span>, <span class="synConstant">'83'</span>, <span class="synConstant">'41'</span>)
</pre>
<p>
というリストになります。代入する先の左辺は、($name, @score)というリストになっているので、
</p>
<pre class="syntax-highlight">
<span class="synStatement">my</span> <span class="synIdentifier">$name</span> = <span class="synConstant">'Hiroshi Yuki'</span>;
<span class="synStatement">my</span> <span class="synIdentifier">@score</span> = (<span class="synConstant">'70'</span>, <span class="synConstant">'83'</span>, <span class="synConstant">'41'</span>);
</pre>
<p>
と同じことになります。
</p>
</blockquote>
<p>
「同じことになる」で済ませられているけど、なんかかなりファジーな気がするんですが。。。でも、直感的と言えば直感的かもしれない。要は「最初のヤツだけ$nameに格納、後は@scoreにまとめちゃって」ということなんだろう。
</p>
<p>
 foreach構文の使い道は他にもあって、「ファイルの各行を読み込む」時にも使うよ。例はこんな感じになる。
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">open</span> (<span class="synIdentifier">FILE</span>, <span class="synConstant">'file.txt'</span>) <span class="synStatement">or</span> <span class="synStatement">die</span> <span class="synConstant">&#34;</span><span class="synIdentifier">$!</span><span class="synConstant">&#34;</span>;
<span class="synStatement">foreach</span> (<span class="synIdentifier">&#60;FILE&#62;</span>) {
<span class="synStatement">print</span> <span class="synIdentifier">$_</span>;
}
<span class="synStatement">close</span> (<span class="synIdentifier">FILE</span>);
</pre>
<p>
説明にはこんな事書いてあったよ!
</p>
<blockquote>
<p>
「リスト」のところには<FILE>と書いてあります。Perlではリストを書くべきところに<FILE>と書くと、FILEというファイルハンドルからすべての行をメモリ上に読み込み、その各行を要素とするリストを作成します。これはPerlの約束です。
</p>
</blockquote>
<p>
 他にも「ディレクトリ内部の各ファイルの繰り返し」にも使えるよ!
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">opendir</span> (<span class="synIdentifier">DIR</span>, <span class="synConstant">'.'</span>) <span class="synStatement">or</span> <span class="synStatement">die</span> <span class="synConstant">&#34;</span><span class="synIdentifier">$!</span><span class="synConstant">&#34;</span>;
<span class="synStatement">foreach</span> (<span class="synStatement">readdir</span>(<span class="synIdentifier">DIR</span>)) {
<span class="synStatement">print</span> <span class="synConstant">&#34;</span><span class="synIdentifier">$_</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>;
}
<span class="synStatement">closedir</span> (<span class="synIdentifier">DIR</span>);
</pre>
<p>
 この前の章でもやったけど、「keysを使うとハッシュを表示できる」よ♪
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">my</span> <span class="synIdentifier">%hash</span> = (
<span class="synConstant">'Kazu'</span> =&#62; <span class="synConstant">10</span>,
<span class="synConstant">'Yukari'</span> =&#62; <span class="synConstant">20</span>,
<span class="synConstant">'Aiko'</span> =&#62; <span class="synConstant">30</span>,
<span class="synConstant">'Nanbu'</span> =&#62; <span class="synConstant">40</span>,
);
<span class="synStatement">foreach</span> (<span class="synStatement">keys</span>(<span class="synIdentifier">%hash</span>)) {
<span class="synStatement">print</span> <span class="synConstant">&#34;</span><span class="synIdentifier">$_</span><span class="synConstant">: </span><span class="synIdentifier">$hash</span><span class="synConstant">{</span><span class="synIdentifier">$_</span><span class="synConstant">}</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>;
}
</pre>
<p>
「keys(%hash)」で「(&#8216;Kazu&#8217;, &#8216;Yukari&#8217;, &#8216;Aiko&#8217;, &#8216;Nanbu&#8217;)」というリストが得られるよ!なにげに「&#8221;$_: $hash{$_}\n&#8221;;」を「&#8221;$_: %hash{$_}\n&#8221;」としてしまい、ややはまる。抜けているなー。
</p>
<h4>
whileを使った繰り返し
</h4>
<p>
 whileの処理はこんな感じになっている:
</p>
<pre class="syntax-highlight">
<span class="synStatement">while</span> (条件式) {
繰り返す処理
}
</pre>
<p>
条件式が満たされている間中はずっと繰り返し処理を行う。例はこんな感じ。
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">open</span> (<span class="synIdentifier">FILE</span>, <span class="synConstant">'temp.txt'</span>) <span class="synStatement">or</span> <span class="synStatement">die</span> <span class="synConstant">&#34;</span><span class="synIdentifier">$!</span><span class="synConstant">&#34;</span>
<span class="synStatement">while</span> (<span class="synStatement">my</span> <span class="synIdentifier">$line</span> = <span class="synIdentifier">&#60;FILE&#62;</span>) {
<span class="synStatement">print</span> <span class="synIdentifier">$line</span>;
}
<span class="synStatement">close</span>(<span class="synIdentifier">FILE</span>);
</pre>
<p>
これを別な書き方にもできる。
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">open</span> (<span class="synIdentifier">FILE</span>, <span class="synConstant">'temp.txt'</span>) <span class="synStatement">or</span> <span class="synStatement">die</span> <span class="synConstant">&#34;</span><span class="synIdentifier">$!</span><span class="synConstant">&#34;</span>
<span class="synStatement">while</span> (<span class="synIdentifier">&#60;FILE&#62;</span>) {
<span class="synStatement">print</span> <span class="synIdentifier">$_</span>;
}
<span class="synStatement">close</span>(<span class="synIdentifier">FILE</span>);
</pre>
<p>
この「$_」の使い方も少し不思議だけど、説明によると:
</p>
<blockquote>
<p>
whileの中で<FILE>を使うと、読んだ行の内容がデフォルト変数$_に代入されます。
</p>
</blockquote>
<p>
というわけで、お約束らしい。
</p>
</div>