C言語-インタプリタminiBASIC |
11. 条件分岐 IF - ELSEIF - ELSE - ENDIF
@ IF文の条件1が真のときプログラムAを実行し、ENDIF文の次の行に移る。
A IF文の条件1が偽で、ELSEIF文の条件2が真のときプログラムBを実行し、ENDIF文の次の行に移る。
B IF文の条件1、ELSEIF文の条件2が偽のときELSE文以降のプログラムCを実行し、ENDIF文の次の行に移る。
プログラムでは、フラグ(目印)用の変数(if_flag)を用意し、条件1が真のときif_flagを1にし、次の文を実行していく。そして、ELSEIF文でif_flag=1のときENDIF文
- 1まで飛ばし、if_flag=0のとき条件2を判定し、if_flagを設定する。
同様にして、フラグ変数if_flagを、条件が真のときは1、偽のときは0、その他(IF-ENDIFの範囲外)では-1として各文を処理する。
条件式(条件1,条件2等)の計算は、関数logicを使用する。
条件によってELSEIF,ELSE,ENDIFに飛ばす処理で、プログラムリスト(配列list)と最終行(last)のデータが必要になる。関数の引数として渡す方法もあるが、ここではグローバル変数に変更する。
int mb_if(int 現在行) { if IF-ENDIFブロック内 二重IF文エラー 次のトークン(条件)取得 条件式の結果を得る if 結果が1である if_flagを1に設定 else if_flagを0に設定 ELSEIF-1,ELSE-1またはENDIF-1まで 飛ばし、現在行を設定する 現在行を返す } int mb_elseif(int 現在行) { if IF-ENDIFブロック外 文法エラー if if_flagが1である ENDIF-1まで飛ばし、現在行を設定 else 次のトークン(条件)取得 条件式の結果を得る if 結果が1である if_flagを1に設定 else if_flagを0に設定 ELSEIF-1,ELSE-1またはENDIF-1まで 飛ばし、現在行を設定する 現在行を返す } int mb_else(int 現在行) { if IF-ENDIFブロック外 文法エラー if if_flagが1である ENDIF-1まで飛ばし、現在行を設定 else if_flagを1に設定 現在行を返す } int mb_endif(int 現在行) { if IF-ENDIFブロック外 文法エラー if_flagを1に設定 現在行を返す }
[mb_cmds6.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: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 175: 176: 177: 185: 186: 187: 209: 210: 211: 236: |
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include "gettoken.h" /* 関数プロトタイプ宣言 外部参照 */ extern double logic(void); /* eval.c */ /* グローバル変数 */ extern double hensuu[26]; /* 変数用(A〜Z) */ extern int for_ln; /* FOR の行番 */ extern int next_ln; /* NEXT の行番 */ extern int if_flag; /* IF フラグ */ extern int last; /* 最終行 */ extern char *list[100]; /* プログラムリスト用 */ int mb_if(int ln) { double ans; int n; if(if_flag != -1){ /* 二重if文の禁止 */ printf("IF-ENDIFブロックの中にIF文があります\n"); exit(1); } get_token(); /* 次のトークン(条件)取得 */ ans = logic(); /* 条件式の計算 */ if(ans == 1.0) /* 条件 真 */ if_flag = 1; else{ /* 条件 偽 */ if_flag = 0; /* 次のESLEIF, ELSEまたはENDIFまで飛ばす */ for(n = ln + 1; n < last; ++n){ /* 次の行から最終行まで調べる */ strcpy(gt_line, list[n]); get_token(); /* 先頭のトークン取得 */ if(!strcmp(token, "ELSEIF") || !strcmp(token, "ELSE") || !strcmp(token, "ENDIF")){ ln = n - 1; /* 現在行をELSE等の行番号-1に設定 */ break; } } if(n == last){ /* 最終行までELSE等がない */ printf("対応するELSEIF, ELSE, ENDIFがありません\n"); exit(1); } } return(ln); } int mb_elseif(int ln) { double ans; int n; if(if_flag == -1){ /* IF-ENDIFブロック外 */ printf("IF-ENDIFブロックの外にELSEIF文があります\n"); exit(1); } if(if_flag == 1){ /* if,elseifが真の時、次のENDIFまで飛ばす */ for(n = ln + 1; n < last; ++n){ /* 次の行から最終行まで調べる */ strcpy(gt_line, list[n]); get_token(); /* 先頭のトークン取得 */ if(!strcmp(token, "ENDIF")){ ln = n - 1; /* 現在行をENDIFの行番号-1に設定 */ break; } } if(n == last){ /* 最終行までENDIDがない */ printf("対応するENDIFがありません\n"); exit(1); } }else{ /* 偽の時、条件を判定 */ get_token(); /* 次のトークン(条件)取得 */ ans = logic(); /* 条件式の計算 */ if(ans == 1.0) /* 条件 真 */ if_flag = 1; else{ /* 条件 偽 */ if_flag = 0; /* 次のESLEIF, ELSEまたはENDIFまで飛ばす */ for(n = ln + 1; n < last; ++n){ /* 次の行から最終行まで調べる */ strcpy(gt_line, list[n]); get_token(); /* 先頭のトークン取得 */ if(!strcmp(token, "ELSEIF") || !strcmp(token, "ELSE") || !strcmp(token, "ENDIF")){ ln = n - 1; /* 現在行をELSE等の行番号に設定 */ break; } } if(n == last){ /* 最終行までELSE等がない */ printf("対応するELSEIF, ELSE, ENDIFがありません\n"); exit(1); } } } return(ln); } int mb_else(int ln) { int n; if(if_flag == -1){ /* IF-ENDIFブロック外 */ printf("IF-ENDIFブロックの外にELSE文があります\n"); exit(1); } if(if_flag == 1){ /* if,elseifが真の時、次のENDIFまで飛ばす */ for(n = ln + 1; n < last; ++n){ /* 次の行から最終行まで調べる */ strcpy(gt_line, list[n]); get_token(); /* 先頭のトークン取得 */ if(!strcmp(token, "ENDIF")){ ln = n - 1; /* 現在行をENDIFの行番号-1に設定 */ break; } } if(n == last){ /* 最終行までENDIDがない */ printf("対応するENDIFがありません\n"); exit(1); } }else /* 偽の時 */ if_flag = 1; return(ln); } int mb_endif(int ln) { if(if_flag == -1){ /* IF-ENDIFブロック外 */ printf("IF-ENDIFブロックの外にENDIF文があります\n"); exit(1); } if_flag = -1; return(ln); } int mb_for(int ln) { <<省 略>> } int mb_next(int ln) { <<省 略>> } void mb_print(void) { <<省 略>> } void mb_input(void) { <<省 略>> } |
[mbas10.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: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: |
#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 int mb_if(int); extern int mb_elseif(int); extern int mb_else(int); extern int mb_endif(int); extern double logic(void); /* eval.c */ /* グローバル変数 */ double hensuu[26]; /* 変数用(A〜Z) */ int for_ln = -1; /* FORとNEXTの行番 */ int next_ln = -1; int if_flag = -1; /* IF フラグ */ char *list[100]; /* プログラムリスト用 */ int last; /* 最終行 */ void main(int argc, char *argv[]) { <<省 略>> else if(!strcmp("NEXT", token)) now = mb_next(now); else if(!strcmp("IF", token)) now = mb_if(now); else if(!strcmp("ELSEIF", token)) now = mb_elseif(now); else if(!strcmp("ELSE", token)) now = mb_else(now); else if(!strcmp("ENDIF", token)) now = mb_endif(now); else if(!strcmp("REM", token)) printf("REM 命令です\n"); else if(isalpha(*token)){ /* 変数(先頭が英字)チェック */ valnum = *token - 'A'; /* 変数番号記憶 */ get_token(); if(*token != '='){ printf("代入文が正しくありません\n"); exit(1); } get_token(); hensuu[valnum] = logic(); /* 計算式処理 */ }else printf("命令以外です\n"); } } |
21,22行目の変数lastと配列listの宣言はmain()から関数外に移動してグローバル変数にしている。したがって、main()内にある変数lastと配列listの宣言は削除する。
INPUT "IF A=12.34 ? A=",A IF A=12.34 THEN PRINT "A=12.34" ELSE PRINT "Not A=12.34" ENDIF INPUT "DATA A=",A INPUT "DATA B=",B IF A=B THEN PRINT "A=B" ELSEIF A<B THEN PRINT "A<B" ELSE PRINT "A>B" ENDIF END |
D:\Data\src>make lcc -c -o mbas10.obj mbas10.c lcc -o mbas.exe mbas10.obj mb_cmds6.obj gettoken.obj eval2.obj lld @link.i D:\Data\src>mbas reidai08.mb IF A=12.34 ? A=12.34 A=12.34 DATA A=12.34 DATA B=12.35 A<B 終了します D:\Data\src>mbas reidai08.mb IF A=12.34 ? A=-12.34 Not A=12.34 DATA A=12.34 DATA B=-12.34 A>B 終了します D:\Data\src>mbas reidai08.mb IF A=12.34 ? A=12.340001 Not A=12.34 DATA A=123.45 DATA B=123.45 A=B 終了します |
Copyright © 2001 Hiroshi Masuda |