Lesson4 For文と配列について

 今回は、前回に引き続いてフロー制御構文について解説していきます。今回取り上げるのはFor...Nextステートメントです。このステートメントは、ループ制御構文の一つで、指定した回数だけForとNextの間の命令を連続して実行するというものです。また例によって例のごとく次のスクリプトを実行してみてください。

Dim intNumber,I
intNumber=0
MsgBox "1から100までの総和を求めます。"
For I=1 To 100 Step 1
	intNumber=intNumber+I
Next
MsgBox "1から100までの総和は" &  intNumber & "です。"

 このスクリプトは、 1から100までの数字の総和を求めるというものです。

 1行目では和を表す変数intNumberと、何回ループしたかを表す変数Iを宣言しています。このようにカンマ(,)で区切ることによって複数の変数を一行で宣言することができます

 2行目は、intNumberを0にしています。VBSでは内部的には整数型・文字列型など複数のデータ型を持っていますが、Dimステートメントで宣言する際には、バリアント型といってすべての変数のタイプを区別せずに宣言します。そのため、変数を宣言した当初はデータ型は決まっていないので、このようにして変数intNumberが数型のデータ型であるということを認識させるわけです。この行はなくても動作します(intNumberを足し算する際、数型のデータ型であることを認識するからです。いったん認識すれば最初は数なら0、文字列なら""という長さ0の文字列が変数にセットされます)が、念のためにおこなっています。

 3から5行目で、For...Next文によるループ処理をおこなっています。3行目のForと5行目のNextの間でループがおこなわれるわけです。
 まず3行目は、「Iを1から100まで、1ずつ変化させて下の行を繰り返す」という意味があります。つまりこの場合は100回繰り返されることになりますね。なお、Step 1 という部分は省略可能です。(省略するとStepは1として実行される)
 4行目では繰り返される命令が記述されています。ここではintNumberにIを足すという命令をおこなっています。このループは1から100まで繰り返される訳なので、最初Iには1が代入されることになり、「intNumber=intNumber+1」という式が実行されることになります。最初intNumberは0なので、この命令が実行されると、intNumberは0+1で1になるわけです。Iが2の時には、「intNumber=intNumber+2」が実行され、intNumberは1+2で3になります。以下、この繰り返しがIが100になるまで繰り返されます。このループが終わったとき、intNumberには1から100までの数の総和が入っていることになります。

 さて、最後の行は計算結果のintNumberを表示させるわけですが、ここで文字列連結記号&を使っています。&を使うと、2つ以上の文字列をつなげて一つの文字列とすることができます。この例では、"1から100までの総和は"と、intNumber(結果は5050になります)と、"です。"という3つの文字列をアンドでつなぐことで、"1から100間での総和は5050です。"という文字列になり、それをMsgBox関数で表示しているわけです。ちなみにintNumberは数型のデータでしたが、このように数型のデータは文字型のデータとして中身を取り出すこともできるわけです。

 次は、For文に配列を導入した例です。

Dim strMsg(4),I
For I=0 To 4
	strMsg(I)=InputBox(I+1 & "番目の文章を入れてください。")
Next
MsgBox "3番目に入力した文章は「" & strMsg(2) & "」です。"

 このスクリプトは、5回文章を入力して、そのうち3回目に入力した文章を表示させるという(って意味があまりないですが、他に例が思いつかなかったので許してくださいまし)スクリプトです。

 1行目で配列を指定した変数を宣言しています。上の例ではstrMsgという変数に、0から4までの配列を指定していることになります。括弧の中身は配列の最大値を示し、また配列の最小値は常に0です。よって配列の数は括弧の中身の数+1となります。この例では、strMsg(0),strMsg(1),strMsg(2),strMsg(3),strMsg(4)という5個の変数を一度に宣言したことになります。
 3行目から4行目では、Iを0から4まで変化させて繰り返し変数に文字列を代入しています。この場合、上の5つの変数にそれぞれ文字列が入ることになります。
 最後の行ではstrMsg(2)、すなわち3つ目に入力した文字列を表示させています。

 

 For文は下のように入れ子構造(ネスト構造ともいう)にもできます。以下の例をご覧ください。

Dim intNumber(2,2),I,J
For I=0 To 2
	For J=0 To 2
		intNumber(I,J)=InputBox(I+1 & "行" & J+1 & "列のデータを入力してください。")
	Next
Next

 このスクリプトは、3×3の行列の値を入力するだけのもので、特に何も起こりません(^^;

 1行目で2次元の配列を宣言しています。括弧の中にコンマで区切った数字を入れておくと、このような多次元の配列が可能です。この例では、intNumber(0,0),intNumber(0,1),intNumber(0,2),intNumber(1,0),intNumber(1,1),intNumber(1,2),intNumber(2,0),intNumber(2,1),intNumber(2,2)の9個の変数がつくられたわけです。

 2行目では最初のループ、3行目では2つ目のループが始まり、それぞれのループは6行目と5行目にあるNextでくくられています。この例では、最初にI=0でJ=0,1,2と繰り返され(つまりintNumber(0,0),intNumber(0,1),intNumber(0,2)に対しておこなわれる)、次にI=1になってまたJ=0,1,2と繰り返され、最後にI=2になってまたJ=0,1,2と繰り返されているので、計9回のインプットボックスによる値入力がおこなわれます。
 この場合の配列は2次元ですが、VBSでは60次元までの配列を設定可能です。

 ところで、配列のサイズを指定せずに配列を宣言する方法もあります。まず、

Dim X()

のように、かっこだけ指定します。
 続いて、コード中で

Redim X(3)

のようにすると、この時XははじめてX(0)〜X(3)の4つの変数を有する配列になります。
 また、この配列のサイズを以下のようにしてさらに変更することもできます。

Redim Preserve X(6)

これは、配列XのX(0)〜X(3)の4つの変数の値を保持したまま配列の大きさを変更するという意味です。よって、X(0)〜X(3)の値はそのままで、X(4)〜X(6)という新たな3つの変数が加わると言うことになります。また、

Redim X(6)

とした場合は、X(0)〜X(3)の値は消去され、新たにX(0)〜X(6)の7つの変数が得られることになります。
 以上の話は、多次元の配列にも適用できますが、1次元の時と若干ふるまいに違いがあります。詳しくはVBSランゲージリファレンスをご覧ください。

 また配列の大きさを調べるにはUBound関数を用います。使い方はUBound (arrayname[,dimension])です。これも詳しくはVBSランゲージリファレンスを…。ちなみに引数の[ ]は、「省略可」の意味ですので覚えておきましょう。UBound関数を用いて、
 

For I=0 To UBound(X)
	...UBound(I)....
Next

もしくはUBoundを用いなくても

For Each I In X
	....I....
Next

のようにすると、配列Xに含まれる変数すべてに対して何らかのコードが記述できます。
 For Each...Nextステートメントは、配列や、コレクションに属する要素すべてに対して繰り返し処理をおこなうというものですが、これについては、「VBS講座・応用編」でコレクションの例とともに再び解説したいと思います。
(コレクションというのは、オブジェクトの集合を格納しているオブジェクトの一種です。)

 さて、ここで1次元配列に関して補足をしておきます。というのも1次元配列は専用の関数を使うと、非常に便利なものだからです。

X=Array("A","B","C","D","E")

X=Split("A B C D E")

上の二つの例は、それぞれArray関数Split関数を用いて、Xに配列を返しています。X(0)="A" , X(1)="B" ...のようになります。これらの関数は、配列の大きさがわからなくても配列を作ることができますし、逐一配列に値を入れなくても一行ですんでしまうなど利点があります。また配列の大きさが知りたければ先ほどのUBound関数を用いればよいのです。この場合、UBound(X)は4という値を返すことになります。

 また、一次元配列は簡単に一つの文字列に直せます。それにはJoin関数を使います。上の配列Xを例に取ると、Join(X)は"A B C D E"という文字列を返します。

 Array,Split,Join関数も詳細は……もうわかりますね。

 

 最後にIf文を併用した、条件分岐によるループ脱出の例です。

Dim intNumber,I
intNumber=0
MsgBox "1から順に数字を足しあわせたとき、最初に1000を越えるのはいつでしょうか?"
For I=1 To 100
	intNumber=intNumber+I
	If intNumber>1000 Then Exit For
Next
MsgBox "1から" & I &  "までの総和は" &  intNumber & "で、このときはじめて1000を越えます。"

 これは、一番最初のスクリプトの変形で、1から順番に数を加えていったとき、最初に1000を越えるのはいつか、を計算するスクリプトです。
 注目していただきたいのは、If intNumber>1000 Then Exit For の部分です。これは「intNumberが1000を越えたとき、ループを抜ける」という内容を表しています。
 ここで>というのは、算数で使う>と同じ意味です。
 また、ここで用いたIf文は、前のLessonで登場したものとは若干形が違います。If として指定する条件に対して、そのとき実行する命令が一つの時、かつElseIf、Elseとして他の条件を指定しない場合は、このようにEnd Ifを省略して1文で記述することができるのです。

If intNumber>1000 Then
	Exit For
End If

のように書いても同じです。
 Exit Forは、ループを抜ける時に使います。この場合、intNumberを繰り返し足しあわせる過程において、もしintNumberが1000を越えれば、その時点で繰り返しをやめ、Nextの次の行に処理を移します。ここではI=45のときintNumberが1035となって1000を越えるので、ここでループを脱出します。Iは100まで繰り返すように指定していますが、Exit Forで抜けると、残りのI=46から100までは実行されなくなります。
 最後の行で結果を表示します。暗算でできましたか?


Lesson4ではFor...Nextステートメントというフロー制御ステートメントおよび配列の概念について解説しました。次のLessonではこの他のフロー制御ステートメントを紹介します。


Home Up Back Next