FreeBASIC マニュアルのトップに戻る

FreeBASIC ProPgTypeIterators

目次→教本→プログラマーのための案内Iterators←オリジナル・サイト

反復子 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい

←リンク元に戻る プログラム開発関連に戻る

多重定義演算子 For, Next, Step を使うと、For ... Next ループのユーザー定義型反復子(組み込みスカラー型反復子だけではなく)を構築できます。

構文 (宣言)
{ Type | Class | Union } typename
暗黙のステップを持つ ' For...Next' 命令文(演算子の最初の構文)
declare Operator For ( )
declare Operator Next ( [ byref | byval ] cond as typename ) as Integer
declare Operator Step ( )
明示的なステップを持つ ' For...Next' 命令文(演算子の2つ目の構文)
declare Operator For ( [ byref | byval ] stp as typename )
declare Operator Next ( [ byref | byval ] cond as typename, [ byref | byval ] stp as typename ) as Integer
declare Operator Step ( [ byref | byval ] stp as typename )
End { Type | Class | Union }

用法
For iterator [ As typename ] = start_value To end_value [ Step step_value ]
[ ...statements... ]
Next

For...Next 命令文で step_value が指定されていない場合は、演算子の最初の構文が使われます。
step_value が指定されている場合は、2番目の構文が使われ、step オブジェクト(step-value で初期化された)が stp パラメーターを介して渡されます:
- Operator For に、最終の追加の初期化でこれが使われる可能性があるため、
- Operator Next に、反復終了のテストはこれに依存する可能性があるため、
- Operator Step に、反復子オブジェクトを増加するため、
演算子の両方の構文は、同じユーザー定義型で共存できます(メンバーの多重定義のおかげ)(ユーザーコードの For...Next 命令文で明示的な増分を使用する場合と、使用しない場合の両方で)。

パラメータ
(including arguments)
typename
name of the Type, Class, or Union
stp, step_value
a typename object used as an incremental value
iterator
a typename object used as an iterator
cond, end_value
a typename object used as a loop-terminating value
start_value
a typename object used to copy construct or assign to the iterator initially

説明
演算子 For, 演算子 Next, 演算子 Step は、ユーザー定義型定義で多重定義して、その型のオブジェクトを(組み込みスカラー型に対して事前定義されている代わりに) For...Next ループで反復子およびステップ値として使えるようにすることができます。

すべての非静的メンバー手続きとして、3つの演算子は、反復子オブジェクト( For...Next 命令文から start_value 引数値に初期化されている)への参照によるアクセスを許可する、非表示 this パラメーターを渡しました。
Operator Nextcond パラメーターを使うと、For...Next 命令文から end_value 引数値にアクセスできます。
For...Next 命令文で step_value が(引数として)指定されている場合、stp パラメーターにより、3つの演算子で、この値にアクセスできます。

注: For...Next 命令文で step_value が指定されていない場合(暗黙的なステップ)、ユーザー定義型には、デフォルトのコンストラクター(暗黙的または明示的)または変換コンストラクターが必要です。
ユーザーがデフォルトのコンストラクターを定義しても、For...Next ループを初期化するときにコンパイラーがそれを使わないのは、現時点のバグです。

演算子 For
演算子 For は、コピーを作成するか、反復子オブジェクトに割り当て( start_value を使用)た直後に 1回呼び出され、終了オブジェクトを作成( end_value を使用)し、ステップオブジェクトを作成( For...Next 命令文で定義されている場合は step_value を使用)します。
演算子 For を使うと、ループの準備に必要な追加の初期化を実行できます。

演算子 Next
演算子 Next は、反復子オブジェクトが終了値を照合する必要があるたびに呼び出されます。
これは、演算子 For の呼び出し直後に発生し、演算子 Step の呼び出し直後に発生します。
演算子 Next は、ループを終了する必要がある場合はゼロ(0)を返し、ループを繰り返し続ける必要がある場合はゼロ以外を返します。
演算子 Next が初めて呼び出されたとき、For...Next 本体の命令文はまだ実行されていません。
演算子 Next は、For...Next 本体のすべての命令文を実行する前に、いくつかの処理を実行することもできます。

演算子 Step
For...Next 本体のすべての命令文が実行された直後で、反復子オブジェクトを増加するために、演算子 Step が呼び出されます。

高度な使い方
上記の説明で、3つの引数 start_value, end_value, step_valueiterator と同じ型(これは明白な使い方です)でなければならないように思われますが、そうではありません:
- start_value, end_value, step_value の各引数は、任意の型を使えます(それらの間で異なる型であっても、iterator の型と異なる型であっても構いません)。
- 唯一の制約は、start_value 引数から iterator が構築(ローカル iterator の場合)または代入(グローバル iterator の場合)できる可能性があることです(iterator は暗黙のうちに構築または代入されるからです)。
- 同様に、他の引数 end_valuestep_value は、iterator と同じ型のオブジェクトに変換できなければなりません。

アルゴリズム
3つの多重定義演算子の周りの For...Next ループアルゴリズム:
'                       FOR...NEXT loop
'                              V
'                              |
'            constructing/assigning iterator object
'       (This = start_value from For...Next statement)
'                              |
'                   constructing end object
'       (cond = end_value from For...Next statement)
'                              |
'                   if step_value is defined >---------------------.
'                            else                                  :
'                              v                                   v
'                              :                        constructing step object
'                              :               (stp = step_value from For...Next statement)
'                              :                                   :
'                              :<----------------------------------'
'                              |
'                    calling Operator For
'                              |
'     .----------------------->|
'     |                        |
'     |              calling Operator Next
'     |     (if end-condition verified: =0 returned) >-------------.
'     |               (else: <>0 returned)                         |
'     |                        v                                   |
'     |                        |                                   |
'     |            executing For...Next body                       |
'     |                        |                                   |
'     |              calling Operator Step                         |
'     |                        |                                   |
'     '------------------------'                                   |
'                                                                  |
'                                                                  V

暗黙的なステップ値を使って、画面解像度を反復処理するための型:

Type screenResolution
    ' user interface
        Declare Constructor (ByVal colorBit As Long)
        Declare Property colorDepth () As Long
        Declare Property screenWidth () As Long
        Declare Property screenHeigth () As Long
    ' overload iteration operators when Step is not defined in For...Next statement
        Declare Operator For ()
        Declare Operator Next (ByRef iterateCondition As screenResolution) As Integer
        Declare Operator Step ()
    ' internal variables
        Dim As Long colorBit, resolutionWH
End Type

Constructor screenResolution (ByVal colorBit As Long)
    This.colorBit = colorBit
End Constructor

Property screenResolution.colorDepth () As Long
    Return This.colorBit
End Property

Property screenResolution.screenWidth () As Long
    Return HiWord(This.resolutionWH)
End Property

Property screenResolution.screenHeigth () As Long
    Return LoWord(This.resolutionWH)
End Property

Operator screenResolution.For ()
    This.resolutionWH = ScreenList(This.colorBit)
End Operator

Operator screenResolution.Next (ByRef iterateCondition As screenResolution) As Integer
    While This.resolutionWH = 0
        If This.colorBit < iterateCondition.colorBit Then
            This.colorBit += 1
            This.resolutionWH = ScreenList(This.colorBit)
        Else
            Exit While
        End If
    Wend
    Return (This.resolutionWH <> iterateCondition.resolutionWH)
End Operator

Operator screenResolution.Step ()
    This.resolutionWH = ScreenList()
End Operator


Print "Screen resolutions supported within [1 bpp , 64 bpp]:"
For iterator As screenResolution = screenResolution(1) To screenResolution(64)
    Print "    " & iterator.colorDepth & " bpp ",
    Print ":" & iterator.screenWidth & "x" & iterator.screenHeigth
Next iterator
Print "End of supported screen resolutions"

Sleep

出力例:
Screen resolutions supported within [1 bpp , 64 bpp]:
	24 bpp    :320x200
	24 bpp    :320x240
	24 bpp    :400x300
	24 bpp    :512x384
	24 bpp    :640x400
	24 bpp    :640x480
	24 bpp    :800x600
	24 bpp    :1024x768
	24 bpp    :1152x864
	24 bpp    :1280x600
	24 bpp    :1280x720
	24 bpp    :1280x768
	24 bpp    :1280x800
	24 bpp    :1280x960
	24 bpp    :1280x1024
	24 bpp    :1360x768
	24 bpp    :1366x768
	24 bpp    :1400x1050
	24 bpp    :1440x900
	24 bpp    :1600x900
	24 bpp    :1680x1050
	24 bpp    :1920x1080
	32 bpp    :320x200
	32 bpp    :320x240
	32 bpp    :400x300
	32 bpp    :512x384
	32 bpp    :640x400
	32 bpp    :640x480
	32 bpp    :800x600
	32 bpp    :1024x768
	32 bpp    :1152x864
	32 bpp    :1280x600
	32 bpp    :1280x720
	32 bpp    :1280x768
	32 bpp    :1280x800
	32 bpp    :1280x960
	32 bpp    :1280x1024
	32 bpp    :1360x768
	32 bpp    :1366x768
	32 bpp    :1400x1050
	32 bpp    :1440x900
	32 bpp    :1600x900
	32 bpp    :1680x1050
	32 bpp    :1920x1080
End of supported screen resolutions

3つの演算子で明示的なステップ値を使って、分数を反復するための型:
演算子 Step ページのプログラムに比べて改善された例)

Type fraction
    ' user interface
        Declare Constructor (ByVal n As Integer, ByVal d As Integer)
        Declare Operator Cast () As String
    ' overload iteration operators when Step is defined in For...Next statement
        Declare Operator For (ByRef iterateStep As fraction)
        Declare Operator Next (ByRef iterateCondition As fraction, ByRef iterateStep As fraction) As Integer
        Declare Operator Step (ByRef step_var As fraction)
    ' internal variables and cast operator
        As Integer num, den
        Declare Operator Cast () As Double
End Type

Constructor fraction (ByVal n As Integer, ByVal d As Integer)
    This.num = n
    This.den = d
End Constructor

Operator fraction.Cast () As String
    ' search for the highest common factor (a) between numerator and denominator
        Dim As Integer a = Abs(This.num), b = Abs(This.den)
        If a <> 0 Then
            While a <> b
                If a > b Then
                    a -= b
                Else
                    b -= a
                End If
            Wend
        Else
            a = 1
        End If
    ' reduce the fraction
        Return num \ a & "/" & den \ a
End Operator

Operator fraction.Cast () As Double
    Return This.num / This.den
End Operator

Operator fraction.For (ByRef iterateStep As fraction)
    ' search for the least common multiple (a) between the two denominators
        Dim As Integer a = Abs(This.den), b = Abs(iterateStep.den), c = a, d = b
        While a <> b
            If a > b Then
                b += d
            Else
                a += c
            End If
        Wend
    ' align at the same denominator the 2 fractions
        This.num *= a \ This.den
        This.den = a
        iterateStep.num *= a \ iterateStep.den
        iterateStep.den = a
End Operator

Operator fraction.Next (ByRef iterateCondition As fraction, ByRef iterateStep As fraction) As Integer
    If iterateStep.num < 0 Or iterateStep.den < 0 Then
        Return This >= iterateCondition
    Else
        Return This <= iterateCondition
    End If
End Operator

Operator fraction.Step (ByRef iterateStep As fraction)
    This.num += iterateStep.num
End Operator


Print "iteration from 1/8 to 1/2 by step of 1/12:"
For iterator As fraction = fraction(1, 8) To fraction(1, 2) Step fraction(1, 12)
    Print "    " & iterator;
Next
Print
Print
Print "iteration from 7/10 to -8/5 by step of -8/15:"
For iterator As fraction = fraction(7, 10) To fraction(-8, 5) Step fraction(-8, 15)
    Print "    " & iterator;
Next
Print

Sleep

出力:
iteration from 1/8 to 1/2 by step of 1/12:
	1/8    5/24    7/24    3/8    11/24
	
iteration from 7/10 to -8/5 by step of -8/15:
	7/10    1/6    -11/30    -9/10    -43/30

参照
プログラマーのための案内に戻る
←リンク元に戻る プログラム開発関連に戻る

ページ歴史:2020-10-13 02:56:43
日本語翻訳:WATANABE Makoto、原文著作者:fxm

ホームページのトップに戻る

表示-非営利-継承