今回は演算キー(+-×÷=)を実装します。(戻る)
演算キーの処理
演算キーは[+][-][×][÷][%]キーで順に加算、減算、乗算、除算、剰余(あまり)を計算します。
普通の電卓のように押された順番に計算することを前提にしてます。
よって、数学のルールのように[+][-]より[×][÷][%]を優先して計算することはありません。
[%]キーは割った余りのみを求めます。
C/C++言語の%演算ですからパーセント計算ではありません。
演算キーが押されたら前回の演算文字(g_ope)を使って計算します。 その後に前回の演算文字(g_ope)に今回の演算キーを代入します。 さらに表示モード状態(g_mode)を結果メモリに切り替えます。
[=]キーは演算キーと同じように最後に入力された数値を求めるときに使います。
このキーは[ENTER]キーでも同じ効果になるようにします。
[=]キーが押されたら前回の演算文字(g_ope)を使って計算します。 その後に前回の演算文字(g_ope)に[=]キーを代入します。 さらに表示モード状態(g_mode)を結果メモリに切り替えます。 既に結果メモリを表示してる状態では、前回の演算文字(g_ope)に[=]キーを代入するだけです。
上記の日本語のアルゴリズム(文章)通りに演算キーを実装すると次のようになります。
//------------------------------------------------ // 演算キーの処理 //------------------------------------------------ static void pushOpe( int ope ) { if ( g_mode ){ switch ( g_ope ){ CASE OPE_SET: g_ans = g_num; CASE OPE_EQU: g_ans = g_num; CASE OPE_ADD: g_ans += g_num; CASE OPE_SUB: g_ans -= g_num; CASE OPE_MUL: g_ans *= g_num; CASE OPE_DIV: g_ans /= g_num; CASE OPE_MOD: g_ans %= g_num; DEFAULT: return; } g_mode = 0; } g_ope = ope; }
日本語で書かれたアルゴリズム(文章)通りに前回の演算文字(g_ope)を使って計算してます。
また、この演算処理を行うときは表示モード状態(g_mode)が入力メモリを表示してる状態のときだけ行います。
これにより演算キーを続けて押すと単純に演算キーだけが切り替わるようになってます。
その後は日本語のアルゴリズム(文章)通りに表示モード状態(g_mode)が結果メモリを表示する状態に切り替えてます。
つまり、表示モード状態(g_mode)に 0 を代入してる部分がそれです。
また、日本語のアルゴリズム(文章)通りに前回の演算文字(g_ope)に今回の演算キーを代入してます。
つまり、前回の演算文字(g_ope)に ope を代入してる部分ですね。
どうですか。
日本語で書かれたアルゴリズム(文章)通りに演算キーの処理を実装しました。
それでは演算キーを実装した整数電卓のサンプルを紹介します。
サンプル
下のソースコードは訂正キー pushAC、pushCE、pushBS 関数の3つが空っぽですが置数キーと演算キーが実装されてます。
コンパイルすると既に電卓の機能を果たすため「123+456-79=」と入力すると正しく「500」と計算されることが確認できます。
//------------------------------------------------------------------------------ // 整数電卓のサンプル(演算キーの実装) //------------------------------------------------------------------------------ #define _CRT_SECURE_NO_WARNINGS #include <ctype.h> #include <conio.h> #include <stdio.h> //------------------------------------------------ // break 付きのキーワード //------------------------------------------------ #define CASE break;case #define DEFAULT break;default //------------------------------------------------ // 記号定数(制御文字) //------------------------------------------------ #define BEL '\a' #define BS '\b' #define RET '\r' #define ESC '\x1B' //------------------------------------------------ // 記号定数(上限値) //------------------------------------------------ #define MAX_LIMIT (999999999) //------------------------------------------------ // 記号定数(演算文字) //------------------------------------------------ #define OPE_SET (' ') #define OPE_ADD ('+') #define OPE_SUB ('-') #define OPE_MUL ('*') #define OPE_DIV ('/') #define OPE_MOD ('%') #define OPE_EQU ('=') //------------------------------------------------ // グローバル変数 //------------------------------------------------ static int g_mode; // 表示モード状態 static long g_ans; // 結果メモリ変数 static long g_num; // 入力メモリ変数static int g_ope = OPE_SET; // 前回の演算文字//------------------------------------------------ // [AC]キーの処理 //------------------------------------------------ static void pushAC() { } //------------------------------------------------ // [CE]キーの処理 //------------------------------------------------ static void pushCE() { } //------------------------------------------------ // [→]キーの処理 //------------------------------------------------ static void pushBS() { } //------------------------------------------------ // 置数キーの処理 //------------------------------------------------ static void pushNum( int num ) { if ( g_mode == 0 ){ g_mode = 1; g_num = 0; } if ( g_num <= (MAX_LIMIT/10) ){ g_num *= 10; g_num += num; } else{ _putch( BEL ); } }//------------------------------------------------ // 演算キーの処理 //------------------------------------------------ static void pushOpe( int ope ) { if ( g_mode ){ switch ( g_ope ){ CASE OPE_SET: g_ans = g_num; CASE OPE_EQU: g_ans = g_num; CASE OPE_ADD: g_ans += g_num; CASE OPE_SUB: g_ans -= g_num; CASE OPE_MUL: g_ans *= g_num; CASE OPE_DIV: g_ans /= g_num; CASE OPE_MOD: g_ans %= g_num; DEFAULT: return; } g_mode = 0; } g_ope = ope; }//------------------------------------------------ // 整数電卓のコマンドを実行 //------------------------------------------------ extern int calcInput( int ch, long *ans ) { // 置数キー if ( isdigit(ch) ){ pushNum( ch - '0' ); } else switch ( ch ){ // 訂正キー CASE 'A': pushAC(); CASE 'C': pushCE(); CASE BS: pushBS(); // 演算キー CASE '+': pushOpe( OPE_ADD ); CASE '-': pushOpe( OPE_SUB ); CASE '*': pushOpe( OPE_MUL ); CASE '/': pushOpe( OPE_DIV ); CASE '%': pushOpe( OPE_MOD ); CASE '=': pushOpe( OPE_EQU ); CASE RET: pushOpe( OPE_EQU ); DEFAULT: return 0; } if ( ans != NULL ){ *ans = g_ans; } return 1; } //------------------------------------------------ // 整数電卓の文字列を作成 //------------------------------------------------ extern char *calcMaker( char buff[] ) { if ( g_mode ){ sprintf( buff, "NUM:%10d.[%c]", g_num, g_ope ); } else{ sprintf( buff, "ANS:%10d.[%c]", g_ans, g_ope ); } return buff; } //------------------------------------------------ // メイン関数 //------------------------------------------------ int main( void ) { char buff[ 256 ]; long ans = 0; int ch; while ( (ch = _getch()) != ESC ){ if ( calcInput(ch,&ans) ){ printf( "\r%s", calcMaker(buff) ); } } printf( "\n\n最終結果:%+d\n", ans ); return 0; } //------------------------------------------------------------------------------ // End of longcalc4.cpp //------------------------------------------------------------------------------
上記の 着色された場所 が実装した演算キーの処理部分です。
まとめ
上記のソースコードが演算キーも実装して計算が可能になった新しい整数電卓のサンプルです。
今後、訂正キーの pushAC、pushCE、pushBS 関数の中身を実装することで一通り電卓関数は完成です。
ここでのポイントも第1章の電卓観察で演算キーの電卓処理をじっくりと考えて整理してるので、
その日本語の文章通りにコーディング(実装)すれば pushOpe 関数が実装できるという点に気付くことが重要です。
もう一度言いますが、何も考えずにとりあえずソースコードを書くよりもずっとバグもなく実装が短時間で行えます。
つまり、電卓ソフトを作るときには、電卓の処理をじっくりと観察して動作を調べ上げることに時間をかけるべきなのです。
時間のある方は、もう一度、第1章の電卓観察の説明と照らし合わせて演算キーの実装内容を見ると良いでしょう。
※コメント投稿者のブログIDはブログ作成者のみに通知されます