Bootstrap

C语言之为表达式计算器实现定义变量和使用变量功能

C语言之为表达式计算器实现定义变量和使用变量功能

  • 上一篇实现了基本表达式的加减乘除和括号运算功能
  • 这一次的目标是实现定义变量和使用变量功能
  • 增加分号做为分隔符和结束符!!!
  • 变量名为大小字母组合,长度不能超过7个字母!!!
  • 定义变量格式: a = 9;
  • 使用变量格式: a + 100;

重新定义数据类型

  • 将原来的enum定义去掉!!!
/* define express datatype */
typedef enum _ExpressDataType ExprDT;
enum _ExpressDataType {
  DT_OPERATOR,
  DT_INTEGER,
};
  • 直按改为宏定义!!!
/* define express node data type */
#define DT_OPERATOR 0X01
#define DT_INTEGER  0X02
#define DT_VARIABLE 0X03

将表达式结构体定义修改一下

  • 增加成员字符数组name,做为保存变量名的空间!!!
  • 将dt改为字符型,只占1个字节,name占7个字节,做到8字节对齐!!!
/* define express struct */
typedef struct _Express Expr;
struct _Express {
  char name[7]; //variable name
  char dt; //datatype
  union {
    char oval; //operator
    long ival; //integer
  } V;
};

修改输出信息函数

  • 加入输出变量名信息,代码如下:
/* output express value */
void
out_value (Expr expr)
{
  switch (expr.dt)
    {
    case DT_OPERATOR: printf (" %c",  expr.V.oval); break;
    case DT_INTEGER : printf (" %ld", expr.V.ival); break;
    case DT_VARIABLE: printf (" %s",  expr.name);   break;
    }
}

/* output express info */
void
out_info (Expr expr)
{
  switch (expr.dt)
    {
    case DT_OPERATOR: printf (" op : %c\n",  expr.V.oval); break;
    case DT_INTEGER : printf ("int : %ld\n", expr.V.ival); break;
    case DT_VARIABLE: printf ("var : %s\n",  expr.name);   break;
    }
}

提前准备

  • 将转换函数mid_torpn和计算函数compute_rpn_express的定义提前,以便parse_string函数来调用!!!
/* declare here !!! */
/* middle expr to rpn expr */
int
mid_torpn (Expr *expr, Expr *rpn, int elen);

/* compute rpn express */
Expr
compute_rpn_express (Expr *expr, int rlen);
  • 定义get_value函数,根据变量名获取变量值
  • 第一个参数vtab为变量表的指针
  • 第二个参数vlen为变量表的长度
  • 第三个参数name为变量名
/* get value by variable name */
Expr
get_value (Expr *vtab, int vlen, char *name)
{
  Expr rs = {0, 0, 0};
  for (int k = 0; k < vlen; k++)
    {
      if (0 == strcmp (name, vtab[k].name))
	{
	  rs = vtab[k]; break;
	}
    }
  return rs;
}

重新定义parse_string函数

  • parse_string函数定义如下:
  • 第一个参数estr为表达式字符串指针
  • 第二个参数expr为表达式结构数组
  • 第三个参数elen为表达式结构数组的长度
  • 第四个参数vtab为变量表结构数组
  • 第五个参数vlen为保存变量数量的整型指针
/* parse express string to Expr struct array */
int
parse_string (char *estr,  //express string
	      Expr *expr,  //express struct array
	      int elen,    //express struct array length
	      Expr *vtab,  //variable struct array
	      int *vlen)   //how many variable struct in array
  • parse_string函数内部变量定义如下:

  • idx 表达式字符串索引,每读一个字符自增一

  • ep 表达式结构数组索引,每保存一个Expr自增一

  • nbuf 保存数字,长度为32

  • ndx nbuf的索引,每保存一个数字自增一

  • vbuf 保存变量名,长度为8

  • vdx vbuf的索引,每保存一个字母自增一,长度超过7则显示出错信息并退出运行!!!

  • aflag 赋值标志,发现等号后设置

  • vflag 变量标志,发现字母后设置

处理字母和等号

  • 大小写字母 A-Za-z 长度小于等于7,超出则出错退出!!!
  • 遇到等号’=',将字符串保存到变量表中去,同时清空vbuf,vdx置0,aflag置0!

代码如下:

	case 'A'...'Z':
	case 'a'...'z': //letter
	  {
	    vbuf[vdx] = c; vdx++; vflag = 1;
	    if (vdx == 8)
	      {
		printf ("Error: Variable name length bigger than 7!\n");
		exit (0);
	      }
	  }
	  break;

	case '=': //assignment
	  vtab[*vlen].dt = DT_VARIABLE;
	  for (int i = 0; i < 7; i++)
	    vtab[*vlen].name[i] = vbuf[i];
	  memset (vbuf, 0, 7); vdx = 0; aflag = 1; vflag = 0;
	  break;

处理数字

  • 保存数字至表达式结构数组

代码如下:

	case '0'...'9': //number
	  {
	    char n = estr[idx+1];
	    nbuf[ndx] = c; ndx++;
	    if (n == ' ' || n == ')' || n == ';' || n == '\0'|| //number end
		n == '+' || n == '-' || n == '*' || n == '/') //operator
	      {
		long lt = strtol (nbuf, NULL, 10);
		memset (nbuf, 0, 32); nbuf[0] = '+'; ndx = 1;
		expr[ep].dt = DT_INTEGER;
		expr[ep].V.ival = lt; ep++;
	      }
	  }
	  break;

处理分隔符(分号)

  • 当vflag置1时,根据变量名取变量值,保存到表达式结构数组!
  • 当aflag置1时,运算表达式,将结果赋值给变量!

代码如下:

	case ';': //semicolon, Separator
	  {
	    if (vflag == 1)
	      {
		Expr vs = get_value (vtab, *vlen, vbuf);
		//printf ("GOT Variable [%s] : [%ld]\n", vbuf, vs.V.ival);
		expr[ep].V.ival = vs.V.ival;
		expr[ep].dt = DT_INTEGER; ep++;
		memset (vbuf, 0, 7); vdx = 0; vflag = 0;
	      }

	    if (aflag == 1) //compute express
	      {
		int len = ep, rlen;
		Expr rs;
		Expr rpn[128];

		//if (ep == 0) return 0; //do nothing
		rlen = mid_torpn (expr, rpn, ep); //len);
		printf ("--------------------\n");
		rs = compute_rpn_express (rpn, rlen);
		printf ("--------------------\n");
		printf ("Result : [%ld]\n", rs.V.ival);

		vtab[*vlen].V.ival = rs.V.ival;
		printf ("Variable name : [%s], value : [%ld]\n",
			vtab[*vlen].name, vtab[*vlen].V.ival);

		*vlen = *vlen + 1;
		return 0;
	      }
	  }
	  break;

处理运算符加减乘除括号

  • 处理数字的符号,也就是负号问题!
  • 如果vflag置1,查找变量表,将变量的值存入表达式!
  • 保存运算符至表达式结构数组!

代码如下:

	case '+': case '-': case '*': case '/':	case '(': case ')': //operator
	  {
	    if (c == '-') //negative number
	      {
		char n = estr[idx+1];
		if (n >= '0' && n <= '9')
		  {
		    printf ("Info : negative number!\n");
		    nbuf[0] = c; break;
		  }
	      }

	    if (vflag == 1)
	      {
		Expr vs = get_value (vtab, *vlen, vbuf);
		//printf ("GOT Variable [%s] : [%ld]\n", vbuf, vs.V.ival);
		expr[ep].V.ival = vs.V.ival;
		expr[ep].dt = DT_INTEGER; ep++;
		memset (vbuf, 0, 7); vdx = 0; vflag = 0;
	      }

	    //printf ("save a operator : %c\n", c); //save op
	    expr[ep].dt = DT_OPERATOR;
	    expr[ep].V.oval = c; ep++;
	  }
	  break;

交互运算表达式循环

  • 定义表达式字符串es,用来保存从标准输入的字符,定义变量idx为索引
  • 定义表达式结构数组expr,用来保存表达式
  • 定义RPN表达式结构数组rpn,用来保存RPN表达式
  • 定义变量表达式结构数组vart,用来保存变量
  • 定义相关的长度整型变量:
  • len,从字符串解析得到的表达式的长度
  • rlen,转换为RPN表达式后,RPN表达式的长度
  • vlen,变量表的长度
  • 定义返回结果变量rs
  • 如果是变量定义,如:a=9;,则parse_string函数返回值为0,说明无表达式,只有变量定义!!!

代码如下:

/* evalute express */
void
eval_express (void)
{
  char es[1024] = {0}; //save string from stdin
  Expr expr[128]; //save express parse from string
  Expr rpn[128];  //save rpn express from express
  Expr vart[128]; //save variable express parse from string
  Expr rs;        //the result
  int idx = 0;    //index of es
  int len = 0;    //length of express parse from string
  int rlen = 0;   //rpn express length from express
  int vlen = 0;   //variable express length parse from string
  char c;

  printf ("EXPR:> ");
  c = fgetc (stdin);
  while (c != EOF)
    {
      if (c == '\n')
	{
	  len  = parse_string (es, expr, 128, vart, &vlen);
	  if (len == 0)
	    {
	      //get a variable declare express
	      memset (es, 0, 1024); len = 0; rlen = 0; idx = 0;
	      printf ("EXPR:> ");
	      c = fgetc (stdin);
	    }
	  else
	    {
	      rlen = mid_torpn (expr, rpn, len);
	      printf ("------------------------------\n");
	      for (int i = 0; i < rlen; i++)
		out_value (rpn[i]);
	      printf ("\n------------------------------\n");
	      rs = compute_rpn_express (rpn, rlen);
	      printf ("------------------------------\n");
	      printf (" Result : %ld\n", rs.V.ival);
	      memset (es, 0, 1024);
	      len = 0; rlen = 0; idx = 0;
	      printf ("EXPR:> ");
	      c = fgetc (stdin);
	    }
	}
      else
	{
	  es[idx] = c;
	  idx++; c = fgetc (stdin);
	}
    }
}

测试表达式

常规表达式

  • 100+200-300; 100*200/400;
  • 10+2030-50; (10+20)(50-30);
  • (10+(30-20))50; 10+2030/40;

编译运行,达到预期,效果如下:

songvm@ubuntu:~/works/tmpc/boo$ gcc -g pt.c -o pt
songvm@ubuntu:~/works/tmpc/boo$ ./pt
EXPR:> 100+200-300;
------------------------------
 100 200 + 300 -
------------------------------
push 100
push 200
operate : 100 + 200 = 300
push 300
operate : 300 - 300 = 0
------------------------------
 Result : 0
EXPR:> 100*200/400;
------------------------------
 100 200 * 400 /
------------------------------
push 100
push 200
operate : 100 * 200 = 20000
push 400
operate : 20000 / 400 = 50
------------------------------
 Result : 50
EXPR:> 10+20*30-50;
------------------------------
 10 20 30 * + 50 -
------------------------------
push 10
push 20
push 30
operate : 20 * 30 = 600
operate : 10 + 600 = 610
push 50
operate : 610 - 50 = 560
------------------------------
 Result : 560
EXPR:> (10+20)*(50-30);
------------------------------
 10 20 + 50 30 - *
------------------------------
push 10
push 20
operate : 10 + 20 = 30
push 50
push 30
operate : 50 - 30 = 20
operate : 30 * 20 = 600
------------------------------
 Result : 600
EXPR:> (10+(30-20))*50;
------------------------------
 10 30 20 - + 50 *
------------------------------
push 10
push 30
push 20
operate : 30 - 20 = 10
operate : 10 + 10 = 20
push 50
operate : 20 * 50 = 1000
------------------------------
 Result : 1000
EXPR:> 10+20*30/40;
------------------------------
 10 20 30 * 40 / +
------------------------------
push 10
push 20
push 30
operate : 20 * 30 = 600
push 40
operate : 600 / 40 = 15
operate : 10 + 15 = 25
------------------------------
 Result : 25
EXPR:> 

变量表达式

  • 变量简单赋值:a = 100;
  • 变量表达式赋值:b = 9 + 10;
  • 变量赋值变量:c = a + b;
  • 变量赋值变量表达式:d = c - a + b;

编译运行,基本达到预期,效果如下:

songvm@ubuntu:~/works/tmpc/boo$ gcc -g pt.c -o pt
songvm@ubuntu:~/works/tmpc/boo$ ./pt
EXPR:> a = 100;
--------------------
push 100
--------------------
Result : [100]
Variable name : [a], value : [100]
EXPR:> b = 9 + 10;
--------------------
push 9
push 10
operate : 9 + 10 = 19
--------------------
Result : [19]
Variable name : [b], value : [19]
EXPR:> c = a + b;
--------------------
push 100
push 19
operate : 100 + 19 = 119
--------------------
Result : [119]
Variable name : [c], value : [119]
EXPR:> d = c - a + b;
--------------------
push 119
push 100
operate : 119 - 100 = 19
push 19
operate : 19 + 19 = 38
--------------------
Result : [38]
Variable name : [d], value : [38]
EXPR:> a * a - c + d;
------------------------------
 100 100 * 119 - 38 +
------------------------------
push 100
push 100
operate : 100 * 100 = 10000
push 119
operate : 10000 - 119 = 9881
push 38
operate : 9881 + 38 = 9919
------------------------------
 Result : 9919
EXPR:> 

完整源码如下:

/* filename: pt.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* compile : gcc pt.c -o pt */
/*     run : ./pt           */

/* define express node data type */
#define DT_OPERATOR 0X01
#define DT_INTEGER  0X02
#define DT_VARIABLE 0X03

/* define express struct */
typedef struct _Express Expr;
struct _Express {
  char name[7]; //variable name
  char dt; //express datatype
  union {
    char oval; //operator
    long ival; //integer
  } V;
};

/* output express value */
void
out_value (Expr expr)
{
  switch (expr.dt)
    {
    case DT_OPERATOR: printf (" %c",  expr.V.oval); break;
    case DT_INTEGER : printf (" %ld", expr.V.ival); break;
    case DT_VARIABLE: printf (" %s",  expr.name);   break;
    }
}

/* output express info */
void
out_info (Expr expr)
{
  switch (expr.dt)
    {
    case DT_OPERATOR: printf (" op : %c\n",  expr.V.oval); break;
    case DT_INTEGER : printf ("int : %ld\n", expr.V.ival); break;
    case DT_VARIABLE: printf ("var : %s\n",  expr.name);   break;
    }
}

/* declare here !!! */
/* middle expr to rpn expr */
int
mid_torpn (Expr *expr, Expr *rpn, int elen);

/* compute rpn express */
Expr
compute_rpn_express (Expr *expr, int rlen);

/* get value by variable name */
Expr
get_value (Expr *vtab, int vlen, char *name)
{
  Expr rs = {0, 0, 0};
  for (int k = 0; k < vlen; k++)
    {
      if (0 == strcmp (name, vtab[k].name))
	{
	  rs = vtab[k]; break;
	}
    }
  return rs;
}

/* parse express string to Expr struct array */
int
parse_string (char *estr,  //express string
	      Expr *expr,  //express struct array
	      int elen,    //express struct array length
	      Expr *vtab,  //variable struct array
	      int *vlen)   //how many variable struct in array
{
  char nbuf[32] = {0}; //save number
  int  ndx = 1;        //number index
  int  idx = 0;        //express string index
  int  ep = 0;         //expr pointer
  char vbuf[8] = {0};  //save variable name
  int  vdx = 0;        //variable name index
  int  aflag = 0, vflag = 0; //assignment flag, variable flag
  char c;

  nbuf[0] = '+';
  c = estr[idx];
  while (c != 0)
    {
      switch (c)
	{
	case 'A'...'Z':
	case 'a'...'z': //letter
	  {
	    vbuf[vdx] = c; vdx++; vflag = 1;
	    if (vdx == 8)
	      {
		printf ("Error: Variable name length bigger than 7!\n");
		exit (0);
	      }
	  }
	  break;

	case '=': //assignment
	  vtab[*vlen].dt = DT_VARIABLE;
	  for (int i = 0; i < 7; i++)
	    vtab[*vlen].name[i] = vbuf[i];
	  memset (vbuf, 0, 7); vdx = 0; aflag = 1; vflag = 0;
	  break;

	case ';': //semicolon, Separator
	  {
	    if (vflag == 1)
	      {
		Expr vs = get_value (vtab, *vlen, vbuf);
		//printf ("GOT Variable [%s] : [%ld]\n", vbuf, vs.V.ival);
		expr[ep].V.ival = vs.V.ival;
		expr[ep].dt = DT_INTEGER; ep++;
		memset (vbuf, 0, 7); vdx = 0; vflag = 0;
	      }

	    if (aflag == 1) //compute express
	      {
		int len = ep, rlen;
		Expr rs;
		Expr rpn[128];

		//if (ep == 0) return 0; //do nothing
		rlen = mid_torpn (expr, rpn, ep); //len);
		printf ("--------------------\n");
		rs = compute_rpn_express (rpn, rlen);
		printf ("--------------------\n");
		printf ("Result : [%ld]\n", rs.V.ival);

		vtab[*vlen].V.ival = rs.V.ival;
		printf ("Variable name : [%s], value : [%ld]\n",
			vtab[*vlen].name, vtab[*vlen].V.ival);

		*vlen = *vlen + 1;
		return 0;
	      }
	  }
	  break;

	case '0'...'9': //number
	  {
	    char n = estr[idx+1];
	    nbuf[ndx] = c; ndx++;
	    if (n == ' ' || n == ')' || n == ';' || n == '\0'|| //number end
		n == '+' || n == '-' || n == '*' || n == '/') //operator
	      {
		long lt = strtol (nbuf, NULL, 10);
		memset (nbuf, 0, 32); nbuf[0] = '+'; ndx = 1;
		expr[ep].dt = DT_INTEGER;
		expr[ep].V.ival = lt; ep++;
	      }
	  }
	  break;

	case '+': case '-': case '*': case '/':	case '(': case ')': //operator
	  {
	    if (c == '-') //negative number
	      {
		char n = estr[idx+1];
		if (n >= '0' && n <= '9')
		  {
		    printf ("Info : negative number!\n");
		    nbuf[0] = c; break;
		  }
	      }

	    if (vflag == 1)
	      {
		Expr vs = get_value (vtab, *vlen, vbuf);
		//printf ("GOT Variable [%s] : [%ld]\n", vbuf, vs.V.ival);
		expr[ep].V.ival = vs.V.ival;
		expr[ep].dt = DT_INTEGER; ep++;
		memset (vbuf, 0, 7); vdx = 0; vflag = 0;
	      }

	    //printf ("save a operator : %c\n", c); //save op
	    expr[ep].dt = DT_OPERATOR;
	    expr[ep].V.oval = c; ep++;
	  }
	  break;

	case ' ': //space do nothing
	  break;

	default:
	  printf ("Error: Syntax error!\n");
	  exit (0);
	}

      idx++; c = estr[idx]; //next char
    }

  return ep;
}

/* get priority level */
static char
get_plv (char x)
{
  if (x == '+') return 1;
  if (x == '-') return 1;
  if (x == '*') return 2;
  if (x == '/') return 2;
  return 0;
}

/* middle expr to rpn expr */
int
mid_torpn (Expr *expr, Expr *rpn, int elen)
{
  Expr st[8];
  int idx = 0, ip = 0;

  for (int j = 0; j < 8; j++)
    { st[j].dt = 0; st[j].V.oval = 0; }

  for (int i = 0; i < elen; i++)
    {
      Expr et = expr[i];
      switch (et.dt)
	{
	case DT_INTEGER: //number
	  rpn[idx].dt = DT_INTEGER;
	  rpn[idx].V.ival = et.V.ival; idx++;
	  break;

	case DT_OPERATOR: //operator
	  {
	    switch (et.V.oval)
	      {
	      case '+': case '-': case '*': case '/': //operator
		{
		  char lv, lx;
		  if (ip == 0) //stack empty
		    {
		      st[ip].dt = DT_OPERATOR;
		      st[ip].V.oval = et.V.oval; ip++; //push
		      break;
		    }
		  if (st[ip-1].dt == DT_OPERATOR && st[ip-1].V.oval == '(')
		    {
		      st[ip].dt = DT_OPERATOR;
		      st[ip].V.oval = et.V.oval; ip++; //push
		      break;
		    }
		  lv = get_plv (et.V.oval);
		  lx = get_plv (st[ip-1].V.oval);
		  if (lv > lx)
		    {
		      st[ip].dt = DT_OPERATOR;
		      st[ip].V.oval = et.V.oval; ip++; //push
		      break;
		    }
		  else
		    {
		      rpn[idx].dt = DT_OPERATOR;
		      rpn[idx].V.oval = st[ip-1].V.oval; idx++; //out
		      st[ip-1].dt = 0; st[ip-1].V.oval = 0; ip--; //pop
		      while (ip > 0)
			{
			  char lt = get_plv (st[ip-1].V.oval);
			  if (lv > lt)
			    {
			      st[ip].dt = DT_OPERATOR;
			      st[ip].V.oval = et.V.oval; ip++; //push
			      break;
			    }
			  else
			    {
			      rpn[idx].dt = DT_OPERATOR;
			      rpn[idx].V.oval = st[ip-1].V.oval; idx++; //out
			      st[ip-1].dt = 0; st[ip-1].V.oval = 0; ip--; //pop
			    }
			}
		      if (ip == 0)
			{
			  st[ip].dt = DT_OPERATOR;
			  st[ip].V.oval = et.V.oval; ip++; //push
			}
		    }
		}
		break;

	      case '(':
		st[ip].dt = DT_OPERATOR;
		st[ip].V.oval = et.V.oval; ip++; //push
		break;

	      case ')':
		{
		  while (ip > 0)
		    {
		      char ot = st[ip-1].V.oval;
		      if (ot == '(')
			{
			  st[ip-1].dt = 0; st[ip-1].V.oval = 0; ip--; //pop
			  break;
			}
		      else
			{
			  rpn[idx].dt = DT_OPERATOR;
			  rpn[idx].V.oval = st[ip-1].V.oval; idx++; //out
			  st[ip-1].dt = 0; st[ip-1].V.oval = 0; ip--; //pop
			}
		    }
		}
		break;
	      }
	  }
	  break;
	}
    }

  //pop until stack empty
  while (ip > 0)
    {
      rpn[idx].dt = DT_OPERATOR;
      rpn[idx].V.oval = st[ip-1].V.oval; idx++; //out
      st[ip-1].dt = 0; st[ip-1].V.oval = 0; ip--; //pop
    }

  return idx;
}

/* compute rpn express */
Expr
compute_rpn_express (Expr *expr, int rlen)
{
  Expr st[16], rs;
  int ip = 0;

  for (int j = 0; j < 16; j++)
    { st[j].dt = 0; st[j].V.oval = 0;}

  for (int i = 0; i < rlen; i++)
    {
      Expr et = expr[i];
      if (et.dt == DT_INTEGER)
	{
	  st[ip].dt = DT_INTEGER; st[ip].V.ival = et.V.ival; ip++;
	  printf ("push %ld\n", et.V.ival);
	}
      else if (et.dt == DT_OPERATOR)
	{
	  switch (et.V.oval)
	    {
	    case '+':
	      {
		printf ("operate : %ld + %ld = ",
			st[ip-2].V.ival, st[ip-1].V.ival);
		st[ip-2].V.ival = st[ip-2].V.ival + st[ip-1].V.ival;
		printf ("%ld\n", st[ip-2].V.ival);
		st[ip-1].V.oval = 0; ip--;
	      }
	      break;

	    case '-':
	      {
		printf ("operate : %ld - %ld = ",
			st[ip-2].V.ival, st[ip-1].V.ival);
		st[ip-2].V.ival = st[ip-2].V.ival - st[ip-1].V.ival;
		printf ("%ld\n", st[ip-2].V.ival);
		st[ip-1].V.ival = 0; ip--;
	      }
	      break;

	    case '*':
	      {
		printf ("operate : %ld * %ld = ",
			st[ip-2].V.ival, st[ip-1].V.ival);
		st[ip-2].V.ival = st[ip-2].V.ival * st[ip-1].V.ival;
		printf ("%ld\n", st[ip-2].V.ival);
		st[ip-1].V.ival = 0; ip--;
	      }
	      break;

	    case '/':
	      {
		printf ("operate : %ld / %ld = ",
			st[ip-2].V.ival, st[ip-1].V.ival);
		st[ip-2].V.ival = st[ip-2].V.ival / st[ip-1].V.ival;
		printf ("%ld\n", st[ip-2].V.ival);
		st[ip-1].V.ival = 0; ip--;
	      }
	      break;
	    }
	}
    }

  rs.dt = DT_INTEGER;
  rs.V.ival = st[0].V.ival;
  return rs;
}

/* evalute express */
void
eval_express (void)
{
  char es[1024] = {0}; //save string from stdin
  Expr expr[128]; //save express parse from string
  Expr rpn[128];  //save rpn express from express
  Expr vart[128]; //save variable express parse from string
  Expr rs;        //the result
  int idx = 0;    //index of es
  int len = 0;    //length of express parse from string
  int rlen = 0;   //rpn express length from express
  int vlen = 0;   //variable express length parse from string
  char c;

  printf ("EXPR:> ");
  c = fgetc (stdin);
  while (c != EOF)
    {
      if (c == '\n')
	{
	  len  = parse_string (es, expr, 128, vart, &vlen);
	  if (len == 0)
	    {
	      //get a variable declare express
	      memset (es, 0, 1024); len = 0; rlen = 0; idx = 0;
	      printf ("EXPR:> ");
	      c = fgetc (stdin);
	    }
	  else
	    {
	      rlen = mid_torpn (expr, rpn, len);
	      printf ("------------------------------\n");
	      for (int i = 0; i < rlen; i++)
		out_value (rpn[i]);
	      printf ("\n------------------------------\n");
	      rs = compute_rpn_express (rpn, rlen);
	      printf ("------------------------------\n");
	      printf (" Result : %ld\n", rs.V.ival);
	      memset (es, 0, 1024);
	      len = 0; rlen = 0; idx = 0;
	      printf ("EXPR:> ");
	      c = fgetc (stdin);
	    }
	}
      else
	{
	  es[idx] = c;
	  idx++; c = fgetc (stdin);
	}
    }
}

/**/
int
main (int argc, char *argv[])
{
  eval_express ();
  //printf ("Sizeof Expr : %lu\n", sizeof(Expr));
  return 0;
}
//-----(+-*/)-----//
  • 测试虽然通过,感觉还不够充分,盼网友测试回复!
  • 下一步研究给表达式加个调用函数功能!!!
;