📄 一个表达式求值程序.txt
字号:
//This is a version in BC31.
//and can be easily ported to VC.
//and make a dll that can be used by Delphi
/*
this program can caculate expresions.
E => E+T|E-T
T => T*F|T/F
F => F^M
M => (E)|Func(E)|Number
1.main algorithm uses 递归;
2.uses command lines(help for more info)
3.include a demo(esc to cancel)
4.cannot compile in tiny mode
5.last edited at 12.1
mail address: szhao@mail.ustc.edu.cn
*/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <bios.h>
#include <string.h>
#include <conio.h>
#include <stdarg.h>
#include <math.h>
#include <ctype.h>
#include <time.h>
#include <dir.h>
//#define SOUND
#define TIMER
#define PI 3.14159265358979324
extern unsigned _stklen=50000;
#define DOUBLE long double
//#ifdef SOUND
#define GETVALUE 0
#define PUTVALUE 1
#define ERRORBEEP(HZ,TIME) { sound(HZ); \
delay(TIME); \
nosound(); \
}
//#endif
#define IDK_ESC 0x011b
#define IDK_ENTER 0x1c0d
#define IDK_BKSPACE 0x0e08
#define IDK_TAB 0x0f09
#define IDK_INSERT 0x5200
#define IDK_DEL 0x5300
#define IDK_HOME 0x4700
#define IDK_END 0x4f00
#define IDK_SPACE 0x3920
#define IDK_F1 0x3b00
#define IDK_UP 0x4800
#define IDK_DOWN 0x5000
#define IDK_LEFT 0x4b00
#define IDK_RIGHT 0x4d00
#define POS(m) (long)(char far *)m-(long)(char far *)strbuf
#define LOBYTE(m) (m&0x00FF)
#define HIBYTE(m) (m&0xFF00)
#define BKGNDCOLOR 0 //BLACK
#define NORMALCOLOR (BKGNDCOLOR<<4)+5 //yellow
#define RESULTCOLOR (BKGNDCOLOR<<4)+14 //yellow
#define VARCOLOR (BKGNDCOLOR<<4)+9
#define NUMBERCOLOR (BKGNDCOLOR<<4)+11
#define CMDCOLOR (BKGNDCOLOR<<4)+GREEN
#define HISCOLOR (BKGNDCOLOR<<4)+CYAN
#define RESERVEWORDCOLOR (BKGNDCOLOR<<4)+15 //include optr
#define ALERTCOLOR (BKGNDCOLOR<<4)+RED
#define ALERTCOLOR1 (MESSAGEBARBKCOLOR<<4)+RED
#define MESSAGEBARBKCOLOR 7
#define MESSAGEERROR 4
#define TIMECOLOR ((MESSAGEBARBKCOLOR<<4)+9)
#define MESSAGEHELP 0
#define ATTR2 ((MESSAGEBARBKCOLOR<<4)+MESSAGEHELP)
#define ATTR NORMALCOLOR
/////oprator ids
#define ID_OP_ADD 0
#define ID_OP_SUB 1
#define ID_OP_DIV 2
#define ID_OP_MUL 3
#define MAXVAR 100
#define MAXSTEP 100
#define MAXTOKENLEN 100
typedef unsigned int WORD;
#define FUNCNUM 15
char *funcname[]={
"sin",
"cos",
"tg",
"ctg",
"atg",
"actg",
"asin",
"acos",
"sqrt",
"sqr",
"fact",
"log",
"ln",
"abs",
"int"
};
#define ERRNUM 11
enum ERRORCODE
{
ERR_ALLOCATEMEMORY,
ERR_BADPOINTER,
ERR_ILLEAGLEOP,
ERR_VARNOTDEFINED,
ERR_UNDEFINED,
ERR_UNEXPECTEDTOKEN,
ERR_UNEXPECTEDEND,
ERR_UNMATCHKH,
ERR_ILLEAGLENUMBER,
ERR_OVERFLOW,
ERR_TOOLONGTOKEN,
ERR_COMMADLINE,
ERR_FILEOPENERROR,
ERR_PARAERROR,
ERR_NOERROR
};
char *errmsg[]=
{
"Error:cannot allocate memory! At file %s line %d ",
"Error:pointer is bad! At file %s line %d",
"Error:illeagle operator! At file %s line %d",
"Error:bad variable or command! At file %s line %d",
"Error:undefined error! At file %s line %d",
"Error:meet unexpected token! At file %s line %d",
"Error:unexpected end! At file %s line %d",
"Error:unmatch kuo hao! At file %s line %d",
"Error:illeagle number! At file %s line %d",
"Error:over flow ! At file %s line %d",
"Error:the token name too long, less than 11! At file %s line %d",
"Error:command para error! At file %s line %d",
"Error:open file error!At file %s line %d",
"Error:para error!check you paras,At file %s line %d"
};
struct ERROR
{
ERRORCODE err;
WORD pos;//hold pointer in the str
WORD line;
char mod[100];
};
enum BOOL
{
FALSE,
TRUE
};
struct POINT
{
WORD x;
WORD y;
};
enum TOKENTYPE
{
ID_VAR,
ID_FUNC,
ID_NUMBER,
ID_OPTR,
ID_DELIMITER,
ID_COMMAND,
ID_UNKNOWN,
ID_NONE
};
struct TOKEN
{
TOKENTYPE type;
char name[MAXTOKENLEN];
int index;
int pos;
};
#define MAXHISTORY 10
struct STRLIST
{
char *str;
STRLIST *next;
};
#define MAXVARS 100
#define MAXVARLEN 10
struct VARLIST
{
char *name;
DOUBLE value;
VARLIST *next;
};
static STRLIST header={NULL,NULL};
static VARLIST vhead={NULL,0,NULL};
char promptmsg[10]="Math$";
char *defaultmsg="Please input command.Use help to get help.";
char *demostring="In demo mode.Esc To Cancel";
struct COMMAND
{
char *cmd;
BOOL (*proc)();
};
void showmsg2(int attr,const char *__format, ...);
void showmsg(int attr,const char *__format, ...);
void savecursor(POINT *p);
void restorecursor(POINT *p);
void clearwindow();
void clearwindow2();
void seterror(ERRORCODE e,WORD pos,WORD line,char *s);
void handleerror();
BOOL getstring();
BOOL getdemostring();
BOOL init();
BOOL quit();
BOOL getnexttoken();
BOOL commandproc();
BOOL evalexp();
BOOL evalexp0(DOUBLE *answer);
BOOL evalexp1(DOUBLE *answer);
BOOL evalexp2(DOUBLE *answer);
BOOL evalexp3(DOUBLE *answer);
BOOL setvarvalue(char *nid,DOUBLE value);
BOOL showvarvalue(char *nid);
BOOL evalexp5(DOUBLE *answer);
BOOL evalexp4(DOUBLE *answer);
BOOL atom(DOUBLE *answer);
BOOL func(DOUBLE *answer,int index);
BOOL exec(char *str);
BOOL findandinsert(char *s);
int getlistcount();
char *gethisstr(int i);
BOOL findvar(char *name,int flag=GETVALUE,DOUBLE *value=NULL);
BOOL newvar(char *name,DOUBLE value=0);
BOOL delvar(char *name);
BOOL showstrlist();
BOOL flush();
BOOL close();
BOOL help();
BOOL version();
BOOL prompt();
BOOL cls();
BOOL funclist();
BOOL sound();
BOOL listvars();
BOOL delvars();
BOOL load();
BOOL dir();
BOOL cd();
BOOL demo();
BOOL installtimer();
BOOL uninstalltimer();
#define CMDNUM 16
COMMAND cmdtab[]=
{
{"quit",close},
{"close",close},
{"ver",version},
{"help",help},
{"cls",cls},
{"prompt",prompt},
{"list",showstrlist},
{"flush",flush},
{"funclist",funclist},
{"sound",sound},
{"lv",listvars},
{"del",delvars},
{"load",load},
{"cd",cd},
{"dir",dir},
{"demo",demo}
};
BOOL soundon=TRUE;
ERROR error;
WORD strbuflen;
char *strbuf;
char *pchar;
POINT cursorpos1,cursorpos2;
static int mexit=0;
TOKEN r,r1;
int status=0;
int hispos=0;
int ccc;
int demomode = 1;
BOOL ifshow;
BOOL main()
{
if (!init())handleerror();
while (!mexit)
{
if (demomode ?getdemostring():getstring())
{
ccc=0;
pchar=strbuf;
while (*pchar)
{
if (*pchar=='(') ccc++;
else if (*pchar==')')ccc--;
pchar++;
}
seterror(ERR_NOERROR,0,__LINE__,__FILE__);
if (!evalexp())
{
showmsg2(ALERTCOLOR1,errmsg[error.err],error.mod,error.line);
if (ccc!=0)showmsg(ATTR,"LC-RC=%d \n\r",ccc);
status=error.err+100;
}
else
showmsg2(ATTR2,demomode?demostring:defaultmsg);
}
// if ((strlen(strbuf)<79-strlen(promptmsg)) && (strlen(strbuf)>0))
if (strlen(strbuf))
if(strcmp(strbuf,"flush"))
findandinsert(strbuf);
memset(strbuf,0,strbuflen);
showmsg(ATTR,"\n\r%s",promptmsg);
}
if (quit())
return TRUE;
return FALSE;
}
BOOL init()
{
#ifdef TIMER
installtimer();
#endif
clearwindow();
clearwindow2();
strbuflen=2000;
strbuf=new char[strbuflen+1];
if (!strbuf)
{
seterror(ERR_ALLOCATEMEMORY,0,__LINE__,__FILE__);
return FALSE;
}
memset(strbuf,0,strbuflen);
ifshow = FALSE;
exec("pi=3.1415926");
exec("e = 1");
exec("n = 1");
ifshow = TRUE;
showmsg2(ATTR2,defaultmsg);
version();
showmsg(ATTR, "\n\rEnter Into Demo Mode\n\r");
showmsg(ATTR, "\n\r");
showmsg(ATTR,promptmsg);
return TRUE;
};
BOOL close()
{
mexit=1;
return TRUE;
}
BOOL quit()
{
if (strbuf)
delete strbuf;
flush();
#ifdef TIMER
uninstalltimer();
#endif
asm{
mov ax,0x0003
int 0x10
}
return TRUE;
}
BOOL getstring()
{
int e=0;
int key;
int hispos=getlistcount();
int nCount=0,mCount=0;
if (!strbuf)
{
seterror(ERR_BADPOINTER,0,__LINE__,__FILE__);
return FALSE;
}
while (!e)
{
if (bioskey(1))
{
key=bioskey(0);
if (status!=99)
{
status=99;
showmsg2(ATTR2,defaultmsg);
}
}
else
continue;
switch (key)
{
case IDK_ESC:
{
if (nCount>79-strlen(promptmsg))
break;
if (mCount<nCount)
mCount=nCount;
nCount=0;
gotoxy(strlen(promptmsg)+1,wherey());
textattr(ATTR);
clreol();
break;
}
case IDK_ENTER:
e=1;
break;
case IDK_TAB:
break;
case IDK_HOME:
break;
case IDK_END:
break;
case IDK_DEL:
case IDK_BKSPACE:
case IDK_LEFT:
if (nCount>mCount)
mCount=nCount;
if (nCount>0 && wherex()>0)
{
nCount--;
showmsg(ATTR,"\b \b");
}
break;
case IDK_RIGHT:
{
if (nCount<mCount)
{
nCount++;
char c=strbuf[nCount];
strbuf[nCount]=0;
showmsg(ATTR,&strbuf[nCount-1]);
strbuf[nCount]=c;
}
}
break;
case IDK_UP:
if (getlistcount()<1)
break;
if (nCount>79-strlen(promptmsg))
break;
hispos++;
if (hispos>getlistcount()) hispos=1;
strcpy(strbuf,gethisstr(hispos));
nCount=strlen(strbuf);
mCount=0;
gotoxy(strlen(promptmsg)+1,wherey());
textattr(ATTR);
clreol();
gotoxy(strlen(promptmsg)+1,wherey());
showmsg(ATTR,"%s",strbuf);
break;
case IDK_DOWN:
if (getlistcount()<1)
break;
if (nCount>79-strlen(promptmsg))
break;
hispos--;
if (hispos<1) hispos=getlistcount();
strcpy(strbuf,gethisstr(hispos));
nCount=strlen(strbuf);
mCount=0;
gotoxy(strlen(promptmsg)+1,wherey());
textattr(ATTR);
clreol();
gotoxy(strlen(promptmsg)+1,wherey());
showmsg(ATTR,"%s",strbuf);
break;
break;
default:
// showmsg(ATTR,"%4x\n\r",key);
// showmsg(ATTR,promptmsg);
if (LOBYTE(key) && !(*((int far *)MK_FP(0,0x0417)) & 4))
{
if (nCount<strbuflen)
{
strbuf[nCount]=LOBYTE(key);
nCount++;
char c=strbuf[nCount];
strbuf[nCount]=0;
showmsg(ATTR,&strbuf[nCount-1]);
strbuf[nCount]=c;
}
}
break;
}
}
if (nCount==0)
return FALSE;
strbuf[nCount]=0;
return TRUE;
}
void handleerror()
{
for (int i=0;i<error.pos;i++)
{
showmsg(ATTR,"%c",strbuf[i]);
}
showmsg(ALERTCOLOR,"%s\n\r",&strbuf[i]);
showmsg(ALERTCOLOR,"syntax error found!\n\r");
}
void seterror(ERRORCODE e,WORD pos,WORD line,char *s)
{
//#ifdef SOUND
if (soundon)
ERRORBEEP(500,100);
//#endif
error.err=e;
error.pos=pos;
error.line=line;
strcpy(error.mod,s);
}
void savecursor(POINT *p)
{
p->x=wherex();
p->y=wherey();
}
void restorecursor(POINT *p)
{
gotoxy(p->x,p->y);
}
void showmsg(int attr,const char *__format, ...)
{
char *string=(char *)new char[2000];
va_list argptr;
va_start(argptr,__format);
vsprintf(string,__format,argptr);
va_end(argptr);
textattr(attr);
if (ifshow)
cprintf("%s",string);
delete string;
}
void showmsg2(int attr,const char *__format, ...)
{
char *string=(char *)new char[2000];
va_list argptr;
va_start(argptr,__format);
vsprintf(string,__format,argptr);
va_end(argptr);
savecursor(&cursorpos1);
window(1,25,80,25);
// restorecursor(&cursorpos2);
textattr(attr);
clrscr();
cprintf("%s",string);
window(1,1,80,24);
restorecursor(&cursorpos1);
delete string;
}
void clearwindow()
{
textbackground(BKGNDCOLOR);
window(1,1,80,24);
clrscr();
}
void clearwindow2()
{
window(1,25,80,25);
textbackground(MESSAGEBARBKCOLOR);
clrscr();
}
BOOL commandproc()
{
return TRUE;
}
BOOL evalexp()
{
DOUBLE result;
int i;
pchar=strbuf;
getnexttoken();
switch (r.type)
{
case ID_COMMAND:
if (!(*cmdtab[r.index].proc)())
{
showmsg(ALERTCOLOR,"command failed\n\r");
return FALSE;
}
break;
case ID_VAR:
TOKEN r2;
getnexttoken();
if ( r.name[0]=='=')
{
memcpy(&r2,&r1,sizeof(TOKEN));
getnexttoken();
if (!evalexp0(&result))return FALSE;
if (!setvarvalue(r2.name,result))return FALSE;
}
else
goto doexp;
break;
default:
doexp:
pchar=strbuf;
memset(&r,0,sizeof(r));
memset(&r1,0,sizeof(r));
getnexttoken();
if (!evalexp0(&result)) return FALSE;
break;
}
return TRUE;
}
BOOL setvarvalue(char *nid,DOUBLE value)
{
if (!findvar(nid,PUTVALUE,&value))
if (!newvar(nid,value))return FALSE;
return TRUE;
}
BOOL showvarvalue(char *nid)
{
return TRUE;
}
BOOL evalexp0(DOUBLE *answer)
{
showmsg(ATTR,"\n\ryou input:");
if (evalexp1(answer))
{
if (r.type!=ID_NONE)
{
seterror(ERR_UNEXPECTEDEND,r.pos,__LINE__,__FILE__);
handleerror();
return FALSE;
}
showmsg(ATTR,"%s\n\r",strbuf);
if (error.err == ERR_NOERROR)
{
showmsg(ATTR,"the result:");
showmsg(RESULTCOLOR,"%.19LG\n\r",*answer);
}
return TRUE;
}
else
{
handleerror();
return FALSE;
}
}
BOOL evalexp1(DOUBLE *answer)
{
char op=0;
DOUBLE temp;
if ((r.type==ID_DELIMITER) && (r.name[0]=='+'|| r.name[0]=='-'))
{
/* if (r1.name[0]!='(' && r1.pos!=0)
{
seterror(ERR_UNEXPECTEDTOKEN,r.pos,__LINE__,__FILE__);
return FALSE;
}*/
op=r.name[0];
getnexttoken();
}
if (!evalexp2(answer))
return FALSE;
if (op=='-') *answer=-*answer;
while ((op=r.name[0])=='+' || op=='-')
{
getnexttoken();
if (!evalexp2(&temp))
return FALSE;
switch (op)
{
case '-':
*answer=*answer-temp;
break;
case '+':
*answer=*answer+temp;
break;
}
}
/*
if (r1.name[0]!=')' && r1.type!=ID_NUMBER && r1.type!=ID_VAR)
{
seterror(ERR_UNEXPECTEDTOKEN,r.pos,__LINE__,__FILE__);
return FALSE;
} */
return TRUE;
}
BOOL evalexp2(DOUBLE *answer)
{
char op=0;
DOUBLE temp;
if (!evalexp3(answer))
return FALSE;
while ((op=r.name[0])=='*' || op=='/' || op=='%')
{
getnexttoken();
if (!evalexp3(&temp))
return FALSE;
switch (op)
{
case '*':
*answer=*answer*temp;
break;
case '/':
if (temp == 0)
{
seterror(ERR_OVERFLOW,r.pos,__LINE__,__FILE__);
return FALSE;
}
*answer=*answer/temp;
break;
case '%':
*answer=(long)*answer%(long)temp;
break;
default:
seterror(ERR_ILLEAGLEOP,r.pos,__LINE__,__FILE__);
return FALSE;
}
}
return TRUE;
}
BOOL evalexp3(DOUBLE *answer)
{
DOUBLE temp,ex;
if (!evalexp5(answer))
return FALSE;
if ((r.name[0])=='^')
{
getnexttoken();
if (!evalexp3(&temp))
return FALSE;
if (*answer>0)
{
*answer=exp(log(*answer)*temp);
return TRUE;
}
seterror(ERR_ILLEAGLENUMBER,r.pos,__LINE__,__FILE__);
return FALSE;
//seterror
}
return TRUE;
}
BOOL evalexp4(DOUBLE *answer)
{
char op=0;
if ((r.type==ID_DELIMITER) && (r.name[0]=='+'|| r.name[0]=='-'))
{
/* if (r1.name[0]!='(' && r1.pos!=0)
{
seterror(ERR_UNEXPECTEDTOKEN,r.pos,__LINE__,__FILE__);
return FALSE;
}*/
op=r.name[0];
// getnexttoken();
}
if (!evalexp5(answer))
return FALSE;
// if (op=='-')*answer=-*answer;
// return TRUE;
}
BOOL evalexp5(DOUBLE *answer)
{
int index;
if (r.type ==ID_FUNC)
{
index=r.index;
getnexttoken();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -