プログラミングのメモ帳(C/C++/HSP)

日々のプログラミングで気づいた点や小技集を紹介します。(Windows 10/XP/Vista、VC2017、HSP)

訂正キーの実装

2012年04月09日 20時40分05秒 | アルゴリズム関連

今回は訂正キーの3つ(AC・CE・→)を実装します。(戻る)

[AC]キーの処理

訂正キーの1つでオールクリアを行わせます。
このキーは全てを初期化するためのキーです。

結果メモリ(g_ans)、入力メモリ(g_num)にゼロを代入します。
前回の演算文字(g_ope)には OPE_SET を代入します。
表示モード状態(g_mode)は結果メモリを表示するように切り替えます。

上記の日本語のアルゴリズム(文章)通りに[AC]キーを実装すると次のようになります。

//------------------------------------------------
// [AC]キーの処理
//------------------------------------------------
static void pushAC()
{
    g_mode      = 0;
    g_num       = 0;
    g_ans       = 0;
    g_ope       = OPE_SET;
}

どうですか。
すごく簡単ですね。
でもこれで十分であり[AC]キーの実装は終わりです。

[CE]キーの処理

訂正キーの1つで入力キャンセルを行わせます。
このキーは入力メモリ(g_num)をクリアするためのキーです。

表示モード状態(g_mode)が入力メモリを表示してるときだけ入力メモリ(g_num)にゼロを代入します。
それ以外の結果メモリを表示してる状態ではビープ音を鳴らします。

上記の日本語のアルゴリズム(文章)通りに[CE]キーを実装すると次のようになります。

//------------------------------------------------
// [CE]キーの処理
//------------------------------------------------
static void pushCE()
{
    if ( g_mode ){
        g_mode      = 1;
        g_num       = 0;
    }
    else{
        _putch( BEL );
    }
}

どうですか。
非常にシンプルですね。
でもこれで十分で[CE]キーの実装も終わりです。

[→]キーの処理

訂正キーの1つで1桁下がり(→)を行わせます。
このキーは入力メモリ(g_num)を1桁削ります。

表示モード状態(g_mode)が入力メモリを表示してるときだけ入力メモリ(g_num)を10で割った値にします。
それ以外の結果メモリを表示してる状態ではビープ音を鳴らします。

上記の日本語のアルゴリズム(文章)通りに[→]キーを実装すると次のようになります。

//------------------------------------------------
// [→]キーの処理
//------------------------------------------------
static void pushBS()
{
    if ( g_mode ){
        g_num /= 10;
    }
    else{
        _putch( BEL );
    }
}

どうですか。
こちらも非常にシンプルです。
でもこれだけで1桁下がりの[→]キーの実装は終わりです。

サンプル

下のソースコードは今まで空っぽだった訂正キー pushAC、pushCE、pushBS 関数の3つを実装してます。
コンパイルすると訂正キーも演算キーも置数キーも使える電卓ソフトが一通り完成します。
訂正キーの[AC]、[CE]、[→]キーは、それぞれ[A]、[C]、[BS]キーで行います。

//------------------------------------------------------------------------------
// 整数電卓のサンプル(訂正キーの実装)
//------------------------------------------------------------------------------
#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() { g_mode = 0; g_num = 0; g_ans = 0; g_ope = OPE_SET; } //------------------------------------------------ // [CE]キーの処理 //------------------------------------------------ static void pushCE() { if ( g_mode ){ g_mode = 1; g_num = 0; } else{ _putch( BEL ); } } //------------------------------------------------ // [→]キーの処理 //------------------------------------------------ static void pushBS() { if ( g_mode ){ g_num /= 10; } else{ _putch( BEL ); } }
//------------------------------------------------ // 置数キーの処理 //------------------------------------------------ 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 longcalc5.cpp //------------------------------------------------------------------------------

上記の 着色された場所 が実装した訂正キーの処理部分です。

まとめ

上記のソースコードが訂正キーも実装した完成バージョンの新しい整数電卓のサンプルです。
今後のテーマは、計算中のゼロ除算エラーオーバーフローの不具合対策でしょう。
このままでは 0 で割ろうとすると「動作を停止しました」というエラー・ダイアログが表示されます。



上記のエラー・ダイアログを出さなくするには 0 で割ろうとしてるかチェックする必要があります。
もしも 0 で割ろうとしたときは、電卓関数がエラーコードを戻り値として戻すなどの処理が必要です。
詳しくは第3章の不具合対策で紹介するので、第2章の基本機能はこれで終わります。

←前へ] [目次] [次へ→

コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 演算キーの実装 | トップ | アクセラレータのチェックシート »
最新の画像もっと見る

コメントを投稿

アルゴリズム関連」カテゴリの最新記事