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) { <<省 略>> } |
[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"); } } |
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 |