C言語でイベントを勉強してみる。
今回は、C言語でイベントを使って電卓のコンソールアプリケーションを作ってみたいと思います。
縛り条件として「if / switch文を使用禁止」という内容で書きたいと思います。
プログラム構成
まずは大まかな流れを説明したいと思います。
今回使用するのは四則計算(+-×÷)のみです。
- +が足し算
- -が引き算
- *が掛け算
- /と%を割り算(小数点以下も計算)
という判別で行います。
今回はイベントを勉強したいだけなので、一次式のみ処理可能にします。
符号毎の処理分岐方法は、入力したキーに割り当てられたアスキーコードを配列の添え字としてイベント関数を呼び出します。
結構力業です(笑)
ざっくりとした処理を状態遷移図で表すと以下のように3段階になります。
それでは、さっそくプログラムを見ていきましょう。
まずはmain関数です。
1 2 3 4 5 6 7 8 9 10 11 12 |
#include"calc.h" void main() { /* 関数テーブル作成 */ tableCreate(); /* 電卓イベント実行 */ event(NULL); return; } |
続いてヘッダー。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#ifndef _CALC_H_ #define _CALC_H_ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<conio.h> void enter(int); void upper(int); void add(int); void sub(int); void mul(int); void quo(int); void event(int); void noCnt(int); void tableCreate(); void stateChg(int); void printAns(int); void(*handler[2][255])(int); #endif // _CALC_H_ |
最後に関数ライブラリです。
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 |
#include"calc.h" /* 項格納関数 */ int item[2] = { 0,0 }; /* 演算子格納関数 */ int sign[2] = { '=','=' }; int state = 0; /* 関数テーブル作成関数 */ void tableCreate() { for (int i = 0; i < 2; i++) { for (int j = 0; j < 255; j++) handler[i][j] = noCnt; } for (int i = 0; i < 2;i++) { for (int j = '0'; j <= '9'; j++) handler[i][j] =upper; } /* state=0 */ handler[0][0] = enter; handler[0][(int)'+'] = stateChg; handler[0][(int)'-'] = stateChg; handler[0][(int)'*'] = stateChg; handler[0][(int)'/'] = stateChg; handler[0][(int)'%'] = stateChg; /* state=1 */ handler[1][0] = enter; handler[1][(int)'+'] = stateChg; handler[1][(int)'-'] = stateChg; handler[1][(int)'*'] = stateChg; handler[1][(int)'/'] = stateChg; handler[1][(int)'%'] = stateChg; handler[1][(int)'='] = stateChg; /* state=2 */ handler[2][(int)'+'] = add; handler[2][(int)'-'] = sub; handler[2][(int)'*'] = mul; handler[2][(int)'/'] = quo; handler[2][(int)'%'] = quo; handler[2][(int)'='] = printAns; } /* イベント関数 */ void event(int n) { (*handler[state][n])(n); } /* 入力関数 */ void enter(int num) { char enterc = NULL; //入力文字格納配列 enterc = _getch(); //入力 event(enterc); //状態遷移 } /* 繰り上げ関数 */ void upper(int num) { num -= (int)'0'; printf("%d",num); item[state] = item[state] * 10 + num; //繰り上げ enter(num); } /* 状態遷移関数 */ void stateChg(int num) { printf(" %c ", num); sign[state] = num; handler[2][0] = handler[2][sign[0]]; state++; event(NULL); } /* 足し算関数 */ void add(int num) { item[0] += item[1]; printAns(item[0]); } /* 引き算関数 */ void sub(int num) { item[0] -= item[1]; printAns(item[0]); } /* 掛け算関数 */ void mul(int num) { item[0] *= item[1]; printAns(item[0]); } /* 割り算関数 */ void quo(int num) { item[0] /= item[1]; printAns(item[0]); } /* 訂正関数 */ void noCnt(int num) { event(NULL); } /* 答案表示関数 */ void printAns(int num) { printf("%d\n", num); state = 0; item[0] = 0; item[1] = 0; event(NULL); } |
といった感じですね。
解説
今回、main.cは見ての通りかなりシンプルです。
6行目で関数を配列へ格納する自作関数「tableCreate関数」を呼び出し、
9行目からイベント関数を呼び出します。
イベント関数の引数としてNULLを渡した際に状態が1(state=0)の時に一番最初の入力待機処理に飛ぶようになっています。
そこから電卓の状態遷移が開始します。
あとは、数値が入力されれば入力待機を繰り返し、演算子で状態が遷移、それ以外の文字列は繰り上げ処理をスキップして入力待機へ戻ります。
この辺は言葉で説明してもややこしいのでプログラムを読んでもらえればと思います。
それでは以上で今回のブログを終わります!
実用性には欠ける使用例ですが、もし良かったら遊びで作ってみてください!