プログラミング

プログラミングに関するフォーラムです。VBAは除きます。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(指定なし : 指定なし)
For Each〜Inの疑問です
投稿日時: 17/04/10 07:59:17
投稿者: hisayanxp

(A)(B)の2つの記述ですが、
(A)
Dim num(2)
num(0) = "X"
num(1) = "Y"
num(2) = "Z"
For Each item In num   
    MsgBox item
Next
※このnumがインスタンスで itemが要素であることは理解しました。itemが特別な意味を持つことから変数を宣言されていないことも納得しました。
 
 
(B)
Dim intNumbers(4),intCounter
For intCounter = 0 To 4 Step 1
intNumbers(intCounter) = intCounter * 2
Next
 
Dim intTemp,strMessage
strMessage = ""
For each intTemp In intNumbers
strMessage = strMessage & intTemp & ","
Next
MsgBox strMessage
 
(B)の記述の intTemp が変数宣言されているのに  For each intTemp In intNumbersのようにまるで(A)のitemと同じように使われているのがピンときません。
intTempはitemと同じ使われ方をすると考えてよいのでしょうか?

回答
投稿日時: 17/04/10 09:29:00
投稿者: sk

引用:
Dim num(2)
num(0) = "X"
num(1) = "Y"
num(2) = "Z"
For Each item In num   
    MsgBox item
Next

引用:
itemが特別な意味を持つことから変数を宣言されていないことも納得しました。

スクリプトの先頭行に Option Explicit ステートメントが
記述されていないため、ここでの item が暗黙的な変数として
解釈されただけでは。
 
( item は VBScript の予約語ではないし、特別な意味もない)
 
MSDN より:
https://msdn.microsoft.com/ja-jp/library/cc392455.aspx
https://msdn.microsoft.com/ja-jp/library/cc392253.aspx
 
----------------------------------------------------------------
Option Explicit
Dim num(2)
num(0) = "X"
num(1) = "Y"
num(2) = "Z"
For Each item In num   
    MsgBox item
Next
----------------------------------------------------------------
 
以上のコードだと、変数の明示的な宣言が強制されるため、
item という名前の変数が宣言されていないことによって
6 行目でエラーが発生します。
 
引用:
Dim intNumbers(4),intCounter
For intCounter = 0 To 4 Step 1
intNumbers(intCounter) = intCounter * 2
Next
  
Dim intTemp,strMessage
strMessage = ""
For each intTemp In intNumbers
strMessage = strMessage & intTemp & ","
Next
MsgBox strMessage
  
(B)の記述の intTemp が変数宣言されているのに
For each intTemp In intNumbersのように
まるで(A)のitemと同じように使われているのがピンときません。
intTempはitemと同じ使われ方をすると考えてよいのでしょうか?

そういうことです。

投稿日時: 17/04/10 16:12:27
投稿者: hisayanxp

skさん
ありがとうございました。
「暗黙的に」判断されることがあることを知って驚きました。
 
Dim num(2)
 num(0) = "X"
 num(1) = "Y"
 num(2) = "Z"
 For Each item In num   
    MsgBox item
 Next
※For Eachの行の前後から判断して item は x,y,zのことだなと判断したんですね。
ただもしOption Explicitとなっている場合はエラーをさせずに上記と同じ内容の記述をする場合、itemを変数宣言しなければならないと思いますが、どのような記述でいいでしょうか?考えましたがさっぱり浮かびませんでした。
 

回答
投稿日時: 17/04/10 17:54:48
投稿者: sk

引用:
※For Eachの行の前後から判断して
item は x,y,zのことだなと判断したんですね。

「Option Explicit ステートメントが記述されていないスクリプトにおいて
  item が暗黙的な変数として解釈されている」ことと、
「For Each ... In ... Next ステートメントにおいて
 配列変数 num の各要素を 1 つずつ参照する際の
 受け皿として、変数 item が用いられている」こととは
別の問題です。
 
引用:
ただもしOption Explicitとなっている場合は
エラーをさせずに上記と同じ内容の記述をする場合、
itemを変数宣言しなければならないと思いますが、
どのような記述でいいでしょうか?

(B) 案と同様に、Dim ステートメントによって
変数 item を明示的に宣言なさればよろしいのでは。
 
(記述例 1 )
-----------------------------------------------
Option Explicit
Dim num(2)
Dim item
num(0) = "X"
num(1) = "Y"
num(2) = "Z"
For Each item In num
    MsgBox item
Next
-----------------------------------------------
 
(記述例 2 )
-----------------------------------------------
Option Explicit
Dim num(2), item
num(0) = "X"
num(1) = "Y"
num(2) = "Z"
For Each item In num
    MsgBox item
Next
-----------------------------------------------

投稿日時: 17/04/11 07:24:53
投稿者: hisayanxp

skさん 丁寧におこたえいただきありがとうございます。
ただどうにも納得いかないことがあります。
たとえばnum(2)の場合は、「num(0) = "X"のように num(0)にはXを格納する」というように定義されていますが、
itemを宣言しても「定義」はされていません。こんな変数の使い方はありですか?
やはり「暗黙的変数」ととらえたほうがよいのでしょうか?「暗黙的変数」でもOption Explicitと書いておき item を変数宣言しておけばエラーが生じないから便宜的にそうしていると思えば良いのでしょうか?
 
 
Option Explicit
 Dim num(2), item
 num(0) = "X"
 num(1) = "Y"
 num(2) = "Z"
 For Each item In num
     MsgBox item
 Next

投稿日時: 17/04/11 07:34:47
投稿者: hisayanxp

skさん 追加の疑問です
 
記述がこんな風なら納得がいくのですが、
 
Dim num(2),item
num(0) = "X"
num(1) = "Y"
num(2) = "Z"
item = "X,Y,Z" や item = num(2) になっていて実行がうまくいけば納得がいくのですが、この内容を
MsgBox item            表す記述は可能でしょうか?
Next
 

回答
投稿日時: 17/04/11 09:33:49
投稿者: mokutachi

VBAが目的ならVBAを直接勉強したほうがいいと個人的には思います。
まあ、考え方は人それぞれですけど、
VBAがやりたくてVBSから始めるというのはちょっと不思議に思ったので。
 
ところで、VBAってことはOfficeで使うのが目的なんですかね。
もし、プログラムの勉強ってことなら
VBAも飛ばして、.Netとかのほうがいいと思います。(それもVBじゃなくてC#とか)
幸い、今は無料で使えるものがありますから。

回答
投稿日時: 17/04/11 12:53:10
投稿者: sk

引用:
たとえばnum(2)の場合は、
「num(0) = "X"のように num(0)にはXを格納する」
というように定義されていますが、
itemを宣言しても「定義」はされていません。
こんな変数の使い方はありですか?

ここでの「定義」が「変数の使用」を意味するなら、
変数 item はちゃんと使用されていますよ。
 
引用:
Dim num(2)
num(0) = "X"
num(1) = "Y"
num(2) = "Z"
For Each item In num   
    MsgBox item
Next

上記のコードを For Each ... Next ステートメントではなく、
For ... Next ステートメントに置き換えると
以下のようなコードになります。
 
---------------------------------------------------
Dim num(2), item, n
num(0) = "X"
num(1) = "Y"
num(2) = "Z"
For n = 0 To 2
    item = num(n)
    MsgBox item
Next
---------------------------------------------------
(ここでのループカウンタの開始値/終了値の指定には
 LBound 関数と UBound 関数を使用すべきだが、
 解説の都合上、敢えて数値リテラルで指定することにした)
 
ここでやっているのは、配列変数 num の要素の数( 3 個)だけ
同じ処理を繰り返し(ループ)、1 回ループするごとに
配列変数 num の各要素( 0 番目の要素、1 番目の要素、2 番目の要素)の値を
順番に変数 item に代入する、というフロー制御です。
 
上記のコードにおいては、
0 回目のループにおいて 変数 item には num(0) の値が、
1 回目のループにおいて 変数 item には num(1) の値が、
2 回目のループにおいて 変数 item には num(2) の値が
それぞれ変数 item に渡されています。
 
要するに n 回目のループにおいて
配列変数 num の n 番目の要素を参照する際に、
「 n 番目の要素の値を受け取る/返す変数」として
item が使用されている、というだけのことです。
 
item 自体が「暗黙的な変数」と「明示的に宣言された変数」の
どちらであろうが、これらのループ処理には何ら影響しません。
 
引用:
やはり「暗黙的変数」ととらえたほうがよいのでしょうか?
「暗黙的変数」でもOption Explicitと書いておき
item を変数宣言しておけばエラーが生じないから
便宜的にそうしていると思えば良いのでしょうか?

恐らく「暗黙的な変数」の意味を誤解されていると思います。
 
・Option Explicit ステートメントが記述されていれば、
 そのスクリプトにおいては変数の宣言を強制される
 (変数の宣言を省略することが出来ない)。
 つまり「暗黙的な変数」という存在自体が認められず、
 使用される変数は全て「明示的に宣言された変数」である
 
・逆に Option Explicit ステートメントが記述されていなければ、
 そのスクリプトにおいては変数の宣言を省略することが出来る。
 (変数の明示的な宣言も勿論出来る)
 
・( Option Explicit ステートメントが記述されていない場合において)
 スクリプトに記述された単語「item」は、
 事前に宣言されている変数の名前のどれとも一致していないが、
 VBScript における予約語のどれでもなく、
 また変数の名前付け規則にも違反していないため、
 インタプリタによるスクリプト解析の結果として
 「この『item』は、そういう名前の変数であるとみなすことにする」と
 暗黙的に解釈、識別されただけである。
 
Option Explicit ステートメントを記述するのは、
「変数であるかどうかが明らかではない単語が記述されてたら即座に警告しろ」
という指定をプログラマが事前にしておくようなものであり、
逆に Option Explicit ステートメントを記述しないのは、
「変数であるかどうかが明らかではない単語が記述されてた場合は
 お前(インタプリタ)の自己解釈に任せる」
という了解をプログラマが暗黙的にしている、
ということに相当します。
 
引用:
記述がこんな風なら納得がいくのですが、
  
Dim num(2),item
num(0) = "X"
num(1) = "Y"
num(2) = "Z"
item = "X,Y,Z" や item = num(2) になっていて
実行がうまくいけば納得がいくのですが、

スカラ変数と配列変数の違いや特性を
充分に理解されていないからではないでしょうか。

回答
投稿日時: 17/04/11 20:33:37
投稿者: MMYS

まず、VBS は初心者向けに設計されています。そのため、
デフォルトでは変数の宣言は必要ありません。(Dimは不要)
実行時に変数が出てきた場合、そのとき自動的に変数が確保されます。
 
一方、Opton Explicitを宣言すると、必ずDimで変数を確保しなければなりません。
For Each も単なる変数ですからOpton Explicitある場合、必ず宣言が必要です。
 
暗黙的確保は初心者のための機能ですが、実際にはこれで混乱する人が多いです。
 
ところで今回のケースは ExcelVBAで
ステップ実行しながら
ローカルウインドウで
変数の値と変数の型を確認すれば理解が早いと思います。
以前のTypeNameのときもローカルウインドウで変数の値および型を確認すれば
理解か早まったと思います。
 

投稿日時: 17/04/13 06:59:41
投稿者: hisayanxp

skさんへ
丁寧にご説明いただきありがとうございました。
まだ理解できない部分もありますが、研究します。
VBSもVBAも、.Netの#VBも貪欲にtryしてみます。