home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- #include <ctype.h>
-
- #define NOERR 0
- #define ERR 1
- #define FUNCMAX 20
- #define PI 3.14159
-
- /*---------- 演算子情報構造体 ----------*/
- typedef struct
- {
- char name[8];
- int prior;
- } FUNC ;
-
- /*---------- 演算子設定 ----------*/
- static FUNC func[FUNCMAX] = {
- { "(", 5 }, { "number", 4 }, { "^", 3 }, { "sqr", 3 },
- { "*", 2 }, { "/", 2 }, { "+", 1 }, { "-", 1 },
- { ")", 0 }, { "sin", 3 }, { "cos", 3 }, { "tan", 3 },
- { "arcsin", 3 }, { "arccos", 3 }, { "arctan", 3 },
- { "log", 3 }, { "ln", 3 }, { "exp", 3 }, { "mod", 3 },
- { "abs", 3 }
- };
-
- int calcvalue( const char *, double * );
- static int CV_get_number( const char *, double *, int *, int );
- static int CV_get_function( const char *, int *, int * );
- static int topcmp( const char *, const char * );
- static void tolowerstr( const char *, char * );
-
- /*---------- main routine ----------*/
- int calcvalue( const char *q, double *v )
- {
- int mem_1[256],mem_2[256];
- double mem_3[256],mem_4[256],value;
- int code,a;
- int *st_1,*st_2;
- double *st_3,*st_4;
- char *p,buf[256];
-
- p = buf;
- tolowerstr( q, p );
- bzero( mem_2, 256 );
- /*----------- 逆ポーランド記法への変換 -----------*/
-
- st_1 = mem_1;
- st_2 = mem_2;
- st_3 = mem_3;
- st_4 = mem_4;
-
- code = 0;
-
- while( *p )
- {
- while( *p == ' ' )
- ++ p;
-
- if( CV_get_number( p, &value, &a, code ) )
- {
- if( CV_get_function( p, &code, &a ) )
- {
- return ERR;
- }
- }
- else
- {
- code = 1;
- }
-
- p += a;
- while( func[code].prior <= func[*st_2].prior && *st_2 != 0 && st_2 > mem_2 )
- {
- *st_1 = *st_2;
- *st_3 = *st_4;
- ++st_1;
- ++st_3;
- --st_2;
- --st_4;
- }
-
- if( code != 8 )
- {
- ++st_2;
- ++st_4;
- *st_2 = code;
- *st_4 = value;
- }
- else
- {
- if( *st_2 != 0 )
- return ERR;
- --st_2;
- --st_4;
- }
- }
-
- while( st_2 > mem_2 )
- {
- *st_1 = *st_2;
- *st_3 = *st_4;
- ++st_1;
- ++st_3;
- --st_2;
- --st_4;
- }
-
- *st_1 = 0xff;
- /*----------- 逆ポーランド記法の計算 ----------*/
-
- st_1 = mem_1;
- st_3 = mem_3;
- st_4 = mem_4;
-
- while( *st_1 != 0xff )
- {
- double x,y,z,dmy;
-
- switch( *st_1 )
- {
- case 1:/*----- 数値 -----*/
- *st_4 = *st_3;
- ++st_4;
- break;
-
- case 2:/*----- 巾乗 (x ^ y) -----*/
- y = *(st_4-1);
- x = *(st_4-2);
- st_4 -= 2;
- if( x < 0 && modf( y, &dmy ) != 0 )
- return ERR;
- z = pow( x, y );
- *st_4 = z;
- ++st_4;
- break;
-
- case 3:/*----- 平方根 (sqr x)[x>=0] -----*/
- x = *(st_4-1);
- --st_4;
- if( x < 0 )
- return ERR;
- z = sqrt( x );
- *st_4 = z;
- ++st_4;
- break;
-
- case 4:/*----- 掛け算 (x * y) -----*/
- y = *(st_4-1);
- x = *(st_4-2);
- st_4 -= 2;
- z = x * y;
- *st_4 = z;
- ++st_4;
- break;
-
- case 5:/*----- 割り算 (x / y)[y!=0] -----*/
- y = *(st_4-1);
- x = *(st_4-2);
- st_4 -= 2;
- z = x / y;
- if( y == 0 )
- return ERR;
- *st_4 = z;
- ++st_4;
- break;
-
- case 6:/*----- 足し算 (x + y) -----*/
- y = *(st_4-1);
- x = *(st_4-2);
- st_4 -= 2;
- z = x + y;
- *st_4 = z;
- ++st_4;
- break;
-
- case 7:/*----- 引き算 (x - y) -----*/
- y = *(st_4-1);
- if( st_4-1 == mem_4 )
- {
- x = 0;
- --st_4;
- }
- else
- {
- x = *(st_4-2);
- st_4 -= 2;
- }
- z = x - y;
- *st_4 = z;
- ++st_4;
- break;
-
- case 9:/*----- 正弦 (sin x) -----*/
- x = *(st_4-1);
- --st_4;
- z = sin( x );
- *st_4 = z;
- ++st_4;
- break;
-
- case 10:/*----- 余弦 (cos x) -----*/
- x = *(st_4-1);
- --st_4;
- z = cos( x );
- *st_4 = z;
- ++st_4;
- break;
-
- case 11:/*----- 正接 (tan x)[x!=PI/2+2*n*PI] -----*/
- x = *(st_4-1);
- --st_4;
- if( modf( fmod( x - PI/2, PI ), &dmy ) == 0 )
- return ERR;
- z = tan( x );
- *st_4 = z;
- ++st_4;
- break;
-
- case 12:/*----- 正弦の逆関数 (Arcsin x)[-1<=x<=1] -----*/
- x = *(st_4-1);
- --st_4;
- if( x > 1 || x < -1 )
- return ERR;
- z = asin( x );
- *st_4 = z;
- ++st_4;
- break;
-
- case 13:/*----- 余弦の逆関数 (Arccos x)[-1<=x<=1] -----*/
- x = *(st_4-1);
- --st_4;
- if( x > 1 || x < -1 )
- return ERR;
- z = acos( x );
- *st_4 = z;
- ++st_4;
- break;
-
- case 14:/*----- 正接の逆関数 (Arctan x) -----*/
- x = *(st_4-1);
- --st_4;
- z = atan( x );
- *st_4 = z;
- ++st_4;
- break;
-
- case 15:/*----- 常用対数 (log x)[x>0] -----*/
- x = *(st_4-1);
- --st_4;
- if( x <= 0 )
- return ERR;
- z = log10( x );
- *st_4 = z;
- ++st_4;
- break;
-
- case 16:/*----- 自然対数 (ln x)[x>0] -----*/
- x = *(st_4-1);
- --st_4;
- if( x <= 0 )
- return ERR;
- z = log( x );
- *st_4 = z;
- ++st_4;
- break;
-
- case 17:/*----- 自然対数の巾乗 (exp x) -----*/
- x = *(st_4-1);
- --st_4;
- z = exp( x );
- *st_4 = z;
- ++st_4;
- break;
-
- case 18:/*----- 剰余 (x mod y)[y!=0] -----*/
- y = *(st_4-1);
- x = *(st_4-2);
- st_4 -= 2;
- if( y == 0 )
- return ERR;
- z = fmod( x, y );
- *st_4 = z;
- ++st_4;
- break;
-
- case 19:/*----- 絶対値 (abs x) -----*/
- x = *(st_4-1);
- --st_4;
- z = fabs( x );
- *st_4 = z;
- ++st_4;
- break;
- }
- ++st_1;
- ++st_3;
- }
-
- *v = *(st_4-1);
-
- return NOERR;
- }
-
- static int CV_get_number( const char *p, double *value, int *a, int code )
- {
- int flg1,flg2,flg3;
- double tmp;
-
- *value = 0;
- *a = 0;
- flg1 = 0;
- flg2 = ERR;
- flg3 = 0;
-
- if( *p == '-' && code != 1 )
- {
- ++ *a;
- ++ p;
- flg3 = 1;
- }
-
- if( *p == '0' && *(p+1) == 'x' )
- {
- p += 2;
- *a += 2;
-
- while( ( *p >= '0' && *p <= '9' ) || ( *p >= 'a' && *p <= 'f' ) )
- {
- *value *= 16;
- if( *p >= '0' && *p <= '9' )
- *value += *p - '0';
- else
- *value += *p - 'a' + 10;
-
- ++ p;
- ++ *a;
- }
- flg2 = NOERR;
- }
- else
- {
- while( ( *p >= '0' && *p <= '9' ) || *p == '.' )
- {
- if( *p == '.' )
- {
- if( flg1 != 0 )
- return ERR;
- flg1 = 1;
- ++ *a;
- ++p;
- continue;
- }
-
- if( flg1 == 0 )
- {
- *value *= 10;
- *value += *p - '0';
- }
- else
- {
- tmp = *p - '0';
- tmp /= pow( 10, flg1 );
- *value += tmp;
- ++flg1;
- }
-
- flg2 = NOERR;
- ++ p;
- ++ *a;
- }
- }
-
- if( flg3 == 1 )
- *value = 0 - *value;
-
- return flg2;
- }
-
- static int CV_get_function( const char *p, int *code, int *a )
- {
- int i;
-
- i = 0;
- while( i < FUNCMAX )
- {
- if( strncmp( p, func[i].name, strlen(func[i].name) ) == 0 /*topcmp( p, func[i].name )*/ )
- {
- *code = i;
- *a = strlen( func[i].name );
- return NOERR;
- }
- ++ i;
- }
- return ERR;
- }
-
- static int topcmp( const char *p, const char *q )
- {
- while( *q )
- {
- if( *p != *q )
- return 0;
- ++p;
- ++q;
- }
- return 1;
- }
-
- static void tolowerstr( const char *in, char *out )
- {
- while( *in )
- *out++ = tolower(*in++);
- *out = 0;
- return;
- }