C言語-インタプリタminiBASIC
前へ 目次へ 次へ 

 9. 繰返し制御文 FOR - NEXT

書式
    FOR 変数 = 式1 TO 式2 [STEP 式3]
        …
    NEXT

 最初にFOR文を実行したときに変数に式1の値が格納され、次の文に移る。
 NEXT文でFOR文に戻ると変数に式3が加算され、式2以下であれば次の文に移り、越えていればNEXT文の次の文に移る。
 一般のBASICとは違い、一度はFOR - NEXT内が実行される。ただし、FOR - NEXTの入れ子、すなわち多重ループのプログラムはできない。

 NEXT文で容易にFOR2文に戻るためにFOR文の行番を記憶しておく(for_ln)。また、繰り返しが終了してNEXT文の次の文に移るのが容易なようにNEXT文の行番(next_ln)も記憶しておく。

int mb_for(int 現在行)
{
    次のトークン(変数名)取得
    if 変数名として正しくない
        変数名エラー
    次のトークン(=)取得
    if = ではない
        文法エラー
    次のトークン(始値)取得
    始値 = 式の計算
    次のトークン(TO)取得
    if TO ではない
         文法エラー
    次のトークン(終値)取得
    終値 = 式の計算
    次のトークン(STEP)取得
    if STEP である
        次のトークン(=)取得
        増分 = 式の計算
    else if STEP なし
        増分 = 1
    else
        文法エラー
    if 1回目のfor
        現在行を for_ln に保存
        変数に始値設定
    else
        変数に増分を加算
        if 始値 <= 終値 && 変数 > 終値 || 始値 > 終値 && 変数 < 終値
              現在行にNEXTの行番号を設定
              for_ln, next_lnを-1に設定
    現在行を返す
}

 始値、終値と増分を取得した後の「式の計算」には関数expressionを使用する。
 「STEPなし」の判定は、取得したトークンが改行コード(\n)であるときである。
 1回目のFORかどうかは、for_ln に行番号が格納されているかどうかで判断する。最初に、グローバル変数for_ln, next_ln には行番号としてはあり得ない数(-1)を格納しておく。したがって、FORループが終了したときも同様に初期化しておく必要がある。

 次に、NEXT文の処理である。

int mb_next(int 現在行)
{
    if for_ln が -1 である
        対応するFORがない(エラー)
    next_lnに現在行を設定
    現在行にfor_lnを設定
    現在行を返す
}
[mb_cmds4.c]
 1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:

93:
94:
95:

120:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "gettoken.h"
/* 関数プロトタイプ宣言 外部参照 */
extern double expression(void); /* eval.c */
/* グローバル変数 */
extern double  hensuu[26];      /* 変数用(A〜Z) */
extern int     for_ln;          /* FOR  の行番 */
extern int     next_ln;         /* NEXT の行番 */

int mb_for(int ln)
{
    char    val;         /* 変数名(番号) */
    double  d1, d2, d3;  /* 始値,終値,増分 */
    
    val = *get_token();     /* 変数名取得 */
    if(!isalpha(val)){      /* 変数名チェック */
        printf("変数名は英字のみです\n");
        exit(1);
    }
    if(*get_token() != '='){        /* "=" 取得 */
        printf("FOR 文エラーです(=)\n");
        exit(1);
    }
    get_token();                    /* 始値取得 */
    @     = expression();
    get_token();                    /* "TO" 取得 */
    if(token[0] != 'T' || token[1] != 'O'){
        printf("FOR 文エラーです(TO)\n");
        exit(1);
    }
    get_token();                    /* 終値取得 */
    A     = expression();
    get_token();                    /* "STEP" 取得 */
    if(!strcmp(token, "STEP")){     /* STEP あり */
        get_token();                /* 増分取得 */
        B     = expression();
    }else if(C                )      /* STEP なし */
        D        ;
    else{
        printf("FOR 文エラーです(STEP)\n");
        exit(1);
    }
    
    val = val - 'A';            /* 変数番号計算 */
    if(E              ){         /* 1回目のFOR */
        for_ln = ln;
        hensuu[val] = d1;
    }else{                      /* 2回目以降 */
        hensuu[val] = hensuu[val] + d3;                    /* FOR 終了 */
        if(d1 <= d2 && d2 < hensuu[val] || d1 > d2 && d2 > hensuu[val]){
            F         ;
            for_ln = next_ln = -1;
        }
    }
    return(ln);
}
int mb_next(int ln)
{
    if(for_ln == G    ){
        printf("対応する FOR がありません\n");
        exit(1);
    }
    next_ln = H    ;
    ln = I              ;
    return(ln);
}
void mb_print(void)
{
<<省 略>>
}
void mb_input(void)
{
<<省 略>>
}
[解答欄] (すべて半角文字で、空白文字もチェックされます。)
@    A    B   C
D   E   F
G   H   I
     
[main08.c]
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:

48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:

83:
84:
85:
86:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "gettoken.h"
/* 関数プロトタイプ宣言 */
extern void mb_print(void);
extern void mb_input(void);
extern int mb_for(int);
extern int mb_next(int);
extern double expression(void);     /* eval.c */
/* グローバル変数 */
double  hensuu[26];         /* 変数用(A〜Z) */
int     for_ln = -1;        /* FORとNEXTの行番 */
int     next_ln = -1;

void main(int argc, char *argv[])
{
<<省 略>>
    /* 命令の処理 */
    for(now = 0; now < last; ++now){
        strcpy(gt_line, list[now]);     /* 字句解析の準備 */
        get_token();                    /* トークンの取得 */
        if(!strcmp("END", token)){      /* 命令の判定 */
            printf("終了します\n");
            exit(1);
        }
        else if(!strcmp("INPUT", token))
            mb_input();
        else if(!strcmp("PRINT", token))
            mb_print();
        else if(!strcmp("FOR", token))
            now = mb_for(now);
        else if(!strcmp("NEXT", token))
            now = mb_next(now);
        else if(!strcmp("IF", token))
            printf("IF 命令です\n");
<<省 略>>
        }else
            printf("命令以外です\n");
    }
}
reidai6.mb
FOR A = 1 TO 5
    PRINT A;" Kai"
NEXT
FOR N=10 TO 23 STEP 6
    PRINT "FOR TEST 1 = ";N
NEXT
FOR N=30 TO 20 STEP -5
    PRINT "FOR TEST 2 = ";N
NEXT
A = 3
FOR X = A-3 TO 10 STEP 4-2+3
    PRINT "FOR TEST 3 = "; X
NEXT X
END
実行結果
D:\Data\src>make
lcc  -c -o mbas08.obj mbas08.c
lcc  -c -o mb_cmds4.obj mb_cmds4.c
lcc -o mbas.exe  mbas08.obj  mb_cmds4.obj gettoken.obj eval.obj
lld @link.i
D:\Data\src>mbas reidai06.mb
1.000000 Kai
2.000000 Kai
3.000000 Kai
4.000000 Kai
5.000000 Kai
FOR TEST 1 = 10.000000
FOR TEST 1 = 16.000000
FOR TEST 1 = 22.000000
FOR TEST 2 = 30.000000
FOR TEST 2 = 25.000000
FOR TEST 2 = 20.000000
FOR TEST 3 = 0.000000
FOR TEST 3 = 5.000000
FOR TEST 3 = 10.000000
終了します


前へ 目次へ 次へ 
Copyright © 2001 Hiroshi Masuda 

 

 

inserted by FC2 system