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

254 lines
12 KiB
Markdown
Raw Normal View History

2019-03-31 11:00:21 +00:00
---
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>