LabVIEWと同様なプログラミングによってWeb Applicationを作成することができるG Web Development Software (以下GWDS)を触ったことがない方に向けて、基本的な事柄を解説していこうという試みです。なお、大部分の事柄は、GWDSの前身であるLabVIEW NXG Web Moduleと共通します。
シリーズ5回目として繰り返し処理を紹介していきます。
この記事は、以下のような方に向けて書いています。
- 処理を繰り返すにはどうすればいいの?
- ループの構造を扱うのに気を付けるべきポイントは?
- ループ構造を使いこなすテクニックを知りたい
もし上記のことに興味があるよ、という方には参考にして頂けるかもしれません。
なお、前回の記事はこちらです。
処理を繰り返す、ループの構造
前回の記事で、GWDSでは様々なデータタイプがあることを紹介してきました。文字列、数値なんかは特に分かりやすく、使いやすいと思います。
一方で、他のプログラミング言語などの経験がない方にとっては馴染みのないデータタイプもあったと思います。そんなデータタイプの内の一つが配列だと思います。
今回の記事の繰り返し処理と配列はかなり相性がいいです。なぜなら、処理を繰り返すということは処理の結果が複数得られる可能性があり、それら得られた複数のデータをひとまとめに扱うためのデータタイプが配列だからです。
その便利さを感じてもらうために、まずは繰り返し処理の内の一つ、Forループから紹介します。
Forループによる繰り返し
他のプログラミング言語でも登場するForループは、簡単に言えば「回数が決まっているループ」です。
ソフト上では以下の部分のパレットにあるのでこれを選択し、ダイアグラムの上でドラッグして枠を広げて配置します。
Forループを使用する際のルールを紹介しますが、以下の話はこのForループ以外にも、様々な「アルゴリズム」に関わるものと共通していることが多いです。GWDSの環境ではこれら「アルゴリズム」に関わるコードは四角い枠組みとして表されます。
もちろんForループにしか適用されないルールというものもありそれは別個紹介しますが、以下の3つはForループ以外(後から紹介するWhileループなど)でも同じだと思ってください。
- その枠組みの中に書いてあるコードしか影響を受けない
- その枠組みの中に書いてあるコードが全て終わってから次の処理に移る
- 枠組みの外から中へ、あるいは中から外へデータを受け渡すことができる(トンネル)
枠組みの中に書いてあるコードしか影響を受けないとは、例えば以下のようなプログラムの場合、繰り返されるのは乱数の発生(Random Number)だけであり、現在の時刻を取得する処理(Get Current Time)は繰り返されません。Forループの中にあるのは乱数発生の関数だけだからですね。(もちろん、下の図のプログラム全体が他のループに入っていない前提です。全体が他のループに入っていたら、丸ごと繰り返されることになります)
また、全て終わってから次の処理に移るとは、以下の図のような状態の場合に乱数発生と和の計算と差の計算が全て処理が終わってからでないと次の繰り返しに進まないという意味になります。
トンネル、についてはこの後具体的に紹介します。
こういったルールを持つ「枠組み」の種類がいくつかあり、繰り返したり、条件分岐に使用したり、特定のイベントが発生したときのみ実行する、などと分かれています。
では、Forループに特有の性質を紹介していきます。
Forループは、上にも書きましたが、何かしらの処理を決まった回数だけ実行する場合に使用します。
Forループには、カウント端子と反復端子という端子が備わっていてプログラムの中で使用できるのですが、下の説明の通り、「決まった回数」を指定するために使用するのはカウント端子です。
- カウント端子:Forループの繰り返しの回数を決める
- 反復端子:今繰り返しの何回目なのかという数値を出力する。ただし数え始めは0から始める
・・・なのですが、Forループの「繰り返し回数」の決め方には実は大きく分けて2種類あります。
具体的な数値で指定する
オーソドックスなのは、具体的に数値で指定する方法です。5回、とか200回とか、そういった数値をカウント端子に指定して繰り返しの回数を決めます。
例えば、何かしらのデータ(下の図では乱数)を10回取得するという場合にはカウント端子を用いて以下のように書くことができます。
この方法は、回数を直接指定するのでわかりやすく便利な反面、場合によっては柔軟性に欠けることがあります。
この方法だけ知っていてもプログラムは書けますが、下で紹介しているもう一つの方法を覚えておくと色々と便利です。
入力配列の大きさで指定する
別の方法としては、入力配列の大きさで指定する方法があります。
LabVIEWでForループを扱う際に覚えておくと便利なのがこの方法で、Forループに配線した配列の大きさがそのまま自動的にForループの回数になります。
ここで、上記のような挙動になる仕組みを説明しようと思います。
上のように、Forループの外から、Forループの中身の処理にデータを渡すとき、Forループの境目には「トンネル」ができます。同様に、Forループの中から外へデータを渡すときにもトンネルができます。
前者が入力トンネル、後者が出力トンネルです。入力は、下の図のように定数でもいいですし、制御器でも構いません。出力トンネルからは表示器しか配線することができません。
Forループの外からワイヤをForループにつなげば入力トンネルが自動的にできますし、Forループの内側から外側にワイヤを配線すると自動的に出力トンネルができます。
Forループの場合、配列のデータを入力すると、デフォルトでは「自動指標付け有効」になります。これは、指標(配列の要素の番号を表わすもの)を付けることで、毎回のループで指標0から順に一つずつ値が使用されることを意味します。
対して、自動指標付けを無効にすることもできます。この場合には、Forループの中で配列はそのまま扱われます。このとき、Forループの回数は指定できていることになりません。回数が指定されない限り、プログラムは実行することができません(そのためエラーマークが表示されます)。
出力トンネルについても同様です。自動指標付けの有効、無効の設定があり、デフォルトでは有効になっています。
基本的にはForループの毎回の結果をそれぞれ取得したい場合が多いと思うので、デフォルトのままの、自動指標付け有効の出力トンネルが便利だと思います。
なお、入力トンネルで自動指標付け有効の配列を配線しているとき、複数のサイズを持つ入力配列があったり、さらに「N」の部分にも数値の指定があった場合には、それらの中で一番繰り返す回数が少ないものが採用されることになります。
なので混乱を避けるためには以下が望ましいと思います。
- 複数の入力配列をつなげている場合にはサイズは統一されるようにする
- 入力配列がある場合には(特別に理由がある場合を除いて)カウント端子に配線しない
Whileループによる繰り返し
上ではForループを紹介しましたが、プログラムに組み込みたい動作としては「あらかじめ回数が決まっている」訳ではないことも多いです。かといって処理自体は繰り返す必要がある場合、Forループでえいやと回数を決めてしまうのではなく、「ある条件を満たしたら繰り返しをやめる」という決まりを設けられたら便利です。
こうした繰り返しの方法がWhileループです。ダイアグラム上でForループと同じパレットの中にあります。ダイアグラム上への用意の仕方も全く同じです。
ループを繰り返すかどうかの判定は、Whileループの右下に出てくるアイコン(条件端子)への入力で決まります。このアイコンにTRUEが入力されたらWhileループが止まります。
定数を渡すこともできますし、何かの演算の結果を条件として止めることもできますが、配線できるデータタイプはブールかあるいはエラークラスタデータです。
例えば、ユーザーがボタンを押すか、エラーが起きたかどちらかの状態で繰り返しを終了する、といった場合には、ORの関数を使用すると便利です。
Whileループは今までにすでに出てきましたよね。GWDSでプロジェクトを新規で作ったとき、デフォルトで用意されているindex.gviwebのダイアグラムにあったのがまさにこれです。
このWhileループがないと、ある処理を一度実行してそれ以降は全く何もしないWeb Applicationができあがります。そういったプログラムを意図的に作る場合でない限り、基本的には常にWhileループの中に処理を書いていくことになります。
WhileループをWeb Applicationの中で役立てる別の例は、何かユーザに入力させて、それが正しい情報であれば次の処理に進めるのに対し、もし間違った入力なのであれば延々と入力を繰り返させるといった処理を設ける場合です。
実際は以下の図は簡単すぎる認証プログラムなのでもう少し工夫をしますが、イメージはこんな感じです。
なお、Whileループの入力および出力トンネルは、Forループと異なり、デフォルトでは自動指標付けが無効になっています。が、有効に変えることもできます。
ループ使用時のテクニック
大まかにForループとWhileループを説明したところで、次にこれらループに関連したテクニックなどを紹介します。
繰り返しのタイミングを制御したい
繰り返す、繰り返すと紹介してきましたが、どんな早さで繰り返すのかは触れてきませんでした。
繰り返す早さは、ループの枠組みだけでは定まっていません。あえていうなら「可能な限り早く繰り返す」状態です。
もちろん、早く繰り返しをして結果を得たい場合もありますが、時間を指定して、ゆっくり繰り返させたい、あるいは意図的に繰り返しの周期を決めたい場合もあると思います。そんなときには「待機」か「次のミリ秒倍数まで待機」の関数を使用します。
Forループ、Whileループどちらにも使用できます。
これら二つの関数はどちらも繰り返しのタイミングを指定しますが、使い方が若干異なります。大雑把には以下のような違いがあります。
- 待機 : 毎回指定した時間待つ(指定単位はミリ秒)
- 次のミリ秒倍数まで待機 : 繰り返しの周期が一定になるように待つ(指定単位はミリ秒)
この二つ、ぱっと見違いが分からないと思います。ただ、文章で書くとそれだけで一つの記事ができてしまうほどで、実際にLabVIEW用に解説した記事がGWDSについても当てはまるようなので、違いを知りたいという場合には以下の記事を参考にしてみてください。
前のループの結果を次のループで使用したい
繰り返しの処理を行う場合に、一つ前の結果を次の繰り返し時に持ち越したいということも多く出てきます。その場合にはシフトレジスタという機能を使用します。これはForループ、Whileループ共通して作成することができます。
作り方の例を紹介します。以下では、2と3を足して、その結果に2を足す、という操作を指定した回数分だけ繰り返しています。
上の3番目の操作で出力トンネルをシフトレジスタに変換していますが、入出力トンネルがなくてもループの枠組みを右クリックしてCreate shift registerでシフトレジスタを単体で作成することもできます。
上の図で完成したプログラムでは、シフトレジスタに渡したデータが次のループで使用される、という動作を繰り返します。
シフトレジスタを使用する際の注意点としては、以下が挙げられます。
- 入力側のシフトレジスタは初期化しないとループの1回目の処理で期待しない結果が得られることがある
- シフトレジスタに自動指標付けの概念がない(敢えて言うなら常に自動指標付けが無効の状態)
入力側のシフトレジスタは特に理由がない限りは基本的に配線をしたほうがいいです。入力側のシフトレジスタに配線することを、初期化する、と言います。
また、シフトレジスタは自動指標付けがないため、例えばForループに配列を配線してもForループの回数を決めることができません。もし仮に自動指標付けチックなことをしたい場合には以下のように組むことになります。
なお、LabVIEWを知っている人は、シフトレジスタを下に延ばして2つ前、3つ前のループの値を使う、スタックシフトレジスタの存在を知っているかもしれませんが、GWDSではスタックシフトレジスタを組むことができても、プログラムの実行ができません。
条件にあった結果だけ出力したい
Forループではデフォルトで、Whileループでは設定を変えることで、出力トンネルは自動指標付け有効な状態として、各繰り返しの結果を配列としてループの外に出すことができていました。
ただ、繰り返したすべての結果をループの外に出したいのではなく、ある条件を満たした結果のみ出したい、という場合もあるかと思います。
そんなときには、出力トンネルの設定で「条件」の端子を設けることができます。この条件の端子には、出力させるデータの条件をブールデータとして配線し、TRUEになった結果のみを出力するように構成できます。
例えば以下のプログラムでは、乱数を10回発生させ、毎回のループで出る乱数の値を0.5と比べ、0.5より大きい値のみForループから出すトンネルを作成している例です。
なお、この図のように同じ出力を複数のトンネルから出すことができますが、その際にワイヤは「分岐」させることになります。GWDSの環境では、Ctrlキーを押しながらクリックすることで、ワイヤの途中から分岐をさせることができます。
Forループも途中で止めたい
場合によっては、繰り返し回数を決められるForループについても、途中で処理を止めたい場合があるかもしれません。そんなときには、Forループに、Whileループの時のような条件端子を用意します。
カウント端子への配線、あるいは自動指標付けを有効にした入力トンネルによってForループの回数を決めたものの、何らかの理由で途中で止めるような操作を付け加えたい場合に使用できます。
ループを止める条件を逆にしたい
Whileループにはデフォルトで、そしてForループには設定次第で、条件端子という、ループを止めるための条件を配線するものがあるという話でした。
通常は、この条件端子にTRUEの情報が入った時点でループを止める、という約束です。ただ、プログラムによっては、TRUEではなくFALSEで止めたい場合があるかもしれません。そんな場合には、FALSEで止まるように条件端子の設定を変えることができます。(Forループにつけられる条件端子も同様です)
今回の記事では繰り返し処理の方法について紹介してきました。プログラムを自由に組もうとしたときに、今回の記事のような「アルゴリズム」に関わる内容の話はどれも大切です。なかなか覚えることが多いと思いますが、書いていくうちに慣れると思います。
次回は今回の内容に少し絡んだ、グラフとチャートの表現について紹介していこうと思います。
もしよろしければ次の記事も見ていってもらえると嬉しいです。
ここまで読んでいただきありがとうございました。
コメント