● リファレンス

single character memory

半角カタカナの一文字を使ってメモリを表現する機能です。
例.

    ア + 12 - ニ

次の文字を使用する事ができます。

    ア イ ウ エ オ カ キ ク ケ コ サ シ ス セ ソ タ チ ツ テ ト ナ ニ ヌ ネ ノ
    ハ ヒ フ ヘ ホ マ ミ ム メ モ ヤ ユ ヨ ラ リ ル レ ロ ワ ン

'ア' 〜 'ン'(0xb1 〜 0xdd)の 45 文字に割り当てられています。


実装

STRCALC_PARAM 構造体のメンバ pmem にメモリの実体の先頭アドレスを設定します。また、有効にするメモリ要素数を memmax に設定します。

例.全てのメモリを使用する場合

    STRCALC_PARAM    prm;
    double           scm[45] = {0};  ← 45 要素が最大

             ・
             ・
             ・

    (StrCalc_init 実行後)

    prm.pmem = scm;
    prm.memmax = sizeof(scm) / sizeof(double);

memmax を 45 よりも小さくすると、範囲を狭める事ができます。
計算式上の半角カタカナが 0 〜 memmax の範囲を超えている場合、STATUS_SCMEMORY_RANGEOVER を返します。例えば、memmax = 5 の場合、'ア' 〜 'オ' の変数が有効になり、その状態で 'カ' 〜 'ン' を指定するとエラーが返されます。


値のセット

StrCalc には single character memory に値をセットする機能は無く、アプリケーションが独自にセットしなければなりません。
代入式の左辺にも指定できません。


無効にする

single character memory を使用しない場合は、メンバpmem に NULL をセットするか、memmax に 0 以下の値をセットします(通常は 0 )。無効にした状態で、計算式に半角カタカナを記述すると STATUS_SCMEMORY_NOTREADY を返します。
関数StrCalc_init を実行した直後は、NULL と 0 がセットされています(デフォルトでは無効状態)。


利点



この機能は、仮引数を持つ計算式を処理するような場合等、アプリケーションが内部処理に利用する事を想定して用意されています。
そのため、操作上の使い易さまでは考慮されていません。直感的に理解し難い表現であり、エンドユーザが誤用する可能性があるので、通常の用途ではアプリケーションのみが利用するようにした方が良いでしょう。


ユーザ定義関数例.

/*
  関数名は任意です。引数は 3 つ。
  登録時に、呼び出し元の STRCALC_PARAM 情報を追加情報として渡します。
*/
double __stdcall    user_func(
                            double              *arg,
                            int                 argcnt,
                            int                 *pret,
                            PSTRCALC_PARAM      pcur)
{
    /*
      呼び出し元情報をそのまま使う事はできないので、ローカルにコピーして
      使用します(「コールバック関数MFUNC」の「注意点」参照の事)。
    */

    STRCALC_PARAM       prm = *pcur;

    /*
      引数1 、引数2 、引数3 が ア 、イ 、ウ に対応する事になります。

      引数が格納されているテーブルは、関数が呼び出される度に確保されるので、
      再帰的な計算を行わせる事も可能です。ただし、その場合は終了条件に注意
      してください。
    */

    prm.str = "tan(ア) * イ - 9.80665 * イ^2 / (2 * ウ^2 * cos(ア)^2)";
    prm.pmem = arg;
    prm.memmax = argcnt;

    *pret = StrCalc(&prm);
    return prm.ans;
}

基本的な事ですが、直にメモリ表現の操作を行う場合は、コード範囲が 0xb1 〜 0xdd になる点に留意してください。char 型で扱うと、符号拡張された時に問題が発生する場合があります。

テスト.single character memory の代入式処理

#include <ctype.h>
#include "sc39.h"

#define MEM_START           0xb1      /* ア */
#define MEM_END             0xdd      /* ン */
#define MEM_MAX             (MEM_END - MEM_START + 1)

int     StrCalc_substitution_SCM(PSTRCALC_PARAM prm,char *ptr,int btemp)
{
    int         c,ret;

    while(isspace(*ptr)) /* 先頭側の空白を飛ばす */
        ptr++;

    /*
      最初の文字が 0xb1 よりも小さい場合は
      標準の代入式処理関数を呼び出す
    */
    if ((c = *(unsigned char *)ptr) < MEM_START)
        return StrCalc_substitution(prm,ptr,btemp,0,0,0);

    /* 次の文字がイコールであるか調べる */
    do{
        ptr++;
    }while(isspace(*ptr));
    if (*ptr != '=')
        return STATUS_NEED_EQUAL;

    /* single character memory が使用禁止であるか調べる */
    if (!prm->pmem || prm->memmax <= 0)
        return STATUS_SCMEMORY_NOTREADY;

    /* インデックスが最大範囲を超えているか調べる */
    if ((c -= MEM_START) > MEM_MAX || c >= prm->memmax)
        return STATUS_SCMEMORY_RANGEOVER;

    /* 右辺の計算とメモリへの代入 */
    prm->str = ptr + 1;
    if ((ret = StrCalc(prm)) != STATUS_NORMAL)
        return ret;
    prm->pmem[c] = prm->ans;

    return STATUS_NORMAL;
}

#include <stdio.h>

void    main(void)
{
    STRCALC_PARAM       prm;
    double              mem[5] = {0};
    char                *pstr;
    int                 ret;

    if (!StrCalc_init(&prm)){
        printf("init err.\n");
        return;
    }

    prm.pmem = mem;
    prm.memmax = sizeof(mem) / sizeof(double);

    pstr = " オ = 1+2+3+4+5";
    ret = StrCalc_substitution_SCM(&prm,pstr,0);

    StrCalc_term(&prm);

    if (ret != STATUS_NORMAL)
        printf("err.%d\n",ret);
    else
        printf("%.16G\n",mem['オ' - 'ア']);
}
テストプログラム ソースファイル(zip)