当前位置: 首页 > article >正文

C语言之实现简单的表达式计算器

C语言之实现简单的表达式计算器

这篇博文是对上一篇博文代码的重构!并在此基础上加了一个eval_express函数,实现表达式的交互计算,初步达到REPL,即读表达式、算表达式、输出结果,这样一个循环。

定义表达式数据类型和输出函数

  • Express结构体,用来保存表达式的节点数据,运算符或数字
  • out_value函数,输出表达式节点的值
  • out_info函数,输出表达式节点的详细信息
  • 以上两个函数做用是在编码过程中输出信息,主要是起到调试做用,注意:必不可少!!!
  • 代码如下:
/* define express datatype */
typedef enum _ExpressDataType ExprDT;
enum _ExpressDataType {
  DT_OPERATOR,
  DT_INTEGER,
};

/* define express struct */
typedef struct _Express Expr;
struct _Express {
  ExprDT dt;
  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;
    }
}

/* 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;
    }
}

将表达式字符串解析成各个节点,并保存到数组中

  • parse_string函数,参数estr是表达式字符串,参数expr是表达式节点数组,参数ensize是数组的长度
  • 测试函数test_pstring,调用parse_string函数,观察输出结果
  • 代码如下:
/* parse express string to Expr struct array */
int
parse_string (char *estr, Expr *expr, int ensize)
{
  char buf[32] = {0};
  int idx = 0, jdx = 1, ep = 0;
  char c;

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

	case '+': case '-': case '*': case '/':	case '(': case ')': //operator
	  {
	    if (c == '-') //negative number
	      {
		char p, n;
		if ((idx-1) < 0)
		  p = ' ';
		else
		  p = estr[idx-1]; //prev char
		n = estr[idx+1]; //next char
		if (p >= '0' && p <= '9')
		  { } //c is a operator, do nothing
		else
		  {
		    if (n >= '0' && n <= '9')
		      { buf[0] = '-'; }
		    break; //negative sign
		  }
	      }
	    expr[ep].dt = DT_OPERATOR;
	    expr[ep].V.oval = c; ep++;
	  }
	  break;

	case ' ': //space do nothing
	  break;

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

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

  return ep;
}

/* test parse_string function */
void
test_pstring (void)
{
  int len = 0;
  Expr expr[128];
  char *es = "-100+200*300+-400";
  //char *es = "(100+200)*(300+400)";

  printf ("Express: %s\n", es);
  printf ("--------------------\n");

  len = parse_string (es, expr, 128);

  for (int i = 0; i < len; i++)
    out_info (expr[i]);
  printf ("--------------------\n");

  printf ("Express:");
  for (int i = 0; i < len; i++)
    out_value (expr[i]);
  printf ("\n");

  printf ("Express nodes : %d\n", len);
  printf ("--------------------\n");
}

/**/
int
main (int argc, char *argv[])
{
  test_pstring ();
  return 0;
}
/******(X(X)X)******/

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

gwsong@ubuntu:/tmp/boo$ gcc pe.c -o pe
gwsong@ubuntu:/tmp/boo$ ./pe
Express: -100+200*300+-400
--------------------
int : -100
 op : +
int : 200
 op : *
int : 300
 op : +
int : -400
--------------------
Express: -100 + 200 * 300 + -400
Express nodes : 7
--------------------
gwsong@ubuntu:/tmp/boo$ 

将中缀表达式数组转换为后缀表达式数组

  • mid_torpn函数,参数expr是中缀表达式数组,即上面解析得的数组,参数rpn是目标后缀表达式数组,参数elen是中缀表达式数组的长度!
  • 代码如下:
/* get priority level */
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
			    }
			  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
			}
		      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;
}

/* test mdi_torpn function */
void
test_midtorpn (void)
{
  int len = 0, rlen = 0;
  Expr expr[128], rpn[128];
  //char *es = "100+200*300+400";
  //char *es = "(100+200)*(300+400)";
  char *es = "100*(300-200)/400";

  len  = parse_string (es, expr, 128);
  rlen = mid_torpn (expr, rpn, len);

  printf ("Express : %s\n", es);
  printf ("--------------------\n");
  for (int i = 0; i < rlen; i++)
    out_info (rpn[i]);

  printf ("--------------------\n");
  printf ("RPN expr:");
  for (int i = 0; i < rlen; i++)
    out_value (rpn[i]);
  printf ("\n");
}

/**/
int
main (int argc, char *argv[])
{
  //test_pstring ();
  test_midtorpn ();
  return 0;
}
/******(X(X)X)******/

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

gwsong@ubuntu:/tmp/boo$ gcc pe.c -o pe
gwsong@ubuntu:/tmp/boo$ ./pe
Express : 100*(300-200)/400
--------------------
int : 100
int : 300
int : 200
 op : -
 op : *
int : 400
 op : /
--------------------
RPN expr: 100 300 200 - * 400 /
gwsong@ubuntu:/tmp/boo$ 

计算后缀表达式,输出计算结果

  • 上面的结果显示输出了正确的后缀表达式
  • compute_rpn_express函数,用数组模拟栈来计算后缀表达式输出计算结果
  • 代码如下:
/* 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;
}

/* test compute_rpn_express function */
void
test_compute_rpn_express (void)
{
  int len = 0, rlen = 0;
  Expr expr[128], rpn[128], rs;
  //char *es = "100+200*300+400";
  //char *es = "(100+200)*(300+400)";
  char *es = "100*(300-200)/400";

  len  = parse_string (es, expr, 128);
  rlen = mid_torpn (expr, rpn, len);

  printf ("Express : %s\n", es);
  printf ("--------------------\n");
  for (int i = 0; i < rlen; i++)
    out_info (rpn[i]);

  printf ("--------------------\n");
  printf ("RPN expr:");
  for (int i = 0; i < rlen; i++)
    out_value (rpn[i]);
  printf ("\n");

  printf ("--------------------\n");
  rs = compute_rpn_express (rpn, rlen);
  printf ("--------------------\n");
  printf (" Result : %ld\n", rs.V.ival);
}

/**/
int
main (int argc, char *argv[])
{
  //test_pstring ();
  //test_midtorpn ();
  test_compute_rpn_express ();
  return 0;
}
/******(X(X)X)******/

编译运行,结果如下:

gwsong@ubuntu:/tmp/boo$ gcc pe.c -o pe
gwsong@ubuntu:/tmp/boo$ ./pe
Express : 100*(300-200)/400
--------------------
int : 100
int : 300
int : 200
 op : -
 op : *
int : 400
 op : /
--------------------
RPN expr: 100 300 200 - * 400 /
--------------------
push 100
push 300
push 200
operate : 300 - 200 = 100
operate : 100 * 100 = 10000
push 400
operate : 10000 / 400 = 25
--------------------
 Result : 25
gwsong@ubuntu:/tmp/boo$ 

做一个交互的计算器,输入表达式,输出计算结果

  • 以上计算结果是正确的,做一个命令行交互的计算器就很容易了!!!
  • REPL, read - evalute - print - loop
  • 读取表达式,计算表达式,输出计算结果,如此循环就可以了!!!
  • 定义buf[1024]来将读取的字符串保存存起来,当输入换行符时,计算buf并输出结果!
  • 退出循环用CTRL-D键,这一点LINUX老手好像都知道!
  • 代码如下:
/* evalute express */
void
eval_express (void)
{
  Expr expr[128], rpn[128], rs;
  char es[1024] = {0};
  int idx = 0, len = 0, rlen = 0;
  char c;

  printf ("REPL:> ");
  c = fgetc (stdin);
  while (c != EOF)
    {
      if (c == '\n')
	{
	  len  = parse_string (es, expr, 128);
	  rlen = mid_torpn (expr, rpn, len);
	  printf ("------------------------------\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 ("REPL:> ");
	  c = fgetc (stdin);
	}
      else
	{
	  es[idx] = c;
	  idx++; c = fgetc (stdin);
	}
    }
}

/**/
int
main (int argc, char *argv[])
{
  //test_pstring ();
  //test_midtorpn ();
  //test_compute_rpn_express ();
  eval_express ();
  return 0;
}
/******(X(X)X)******/

编译运行,效果如下:

gwsong@ubuntu:/tmp/boo$ gcc pe.c -o pe
gwsong@ubuntu:/tmp/boo$ ./pe
REPL:> (100+200)/(90-80)
------------------------------
push 100
push 200
operate : 100 + 200 = 300
push 90
push 80
operate : 90 - 80 = 10
operate : 300 / 10 = 30
------------------------------
 Result : 30
REPL:> 
  • 可以多输入几个表达式测试一下!!!

完整代码如下:

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

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

/* define express datatype */
typedef enum _ExpressDataType ExprDT;
enum _ExpressDataType {
  DT_OPERATOR,
  DT_INTEGER,
};

/* define express struct */
typedef struct _Express Expr;
struct _Express {
  ExprDT dt;
  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;
    }
}

/* 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;
    }
}

/* parse express string to Expr struct array */
int
parse_string (char *estr, Expr *expr, int ensize)
{
  char buf[32] = {0};
  int idx = 0, jdx = 1, ep = 0;
  char c;

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

	case '+': case '-': case '*': case '/':	case '(': case ')': //operator
	  {
	    if (c == '-') //negative number
	      {
		char p, n;
		if ((idx-1) < 0)
		  p = ' ';
		else
		  p = estr[idx-1]; //prev char
		n = estr[idx+1]; //next char
		if (p >= '0' && p <= '9')
		  { } //c is a operator, do nothing
		else
		  {
		    if (n >= '0' && n <= '9')
		      { buf[0] = '-'; }
		    break; //negative sign
		  }
	      }
	    expr[ep].dt = DT_OPERATOR;
	    expr[ep].V.oval = c; ep++;
	  }
	  break;

	case ' ': //space do nothing
	  break;

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

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

  return ep;
}

/* test parse_string function */
void
test_pstring (void)
{
  int len = 0;
  Expr expr[128];
  char *es = "-100+200*300+-400";
  //char *es = "(100+200)*(300+400)";

  printf ("Express: %s\n", es);
  printf ("--------------------\n");

  len = parse_string (es, expr, 128);

  for (int i = 0; i < len; i++)
    out_info (expr[i]);
  printf ("--------------------\n");

  printf ("Express:");
  for (int i = 0; i < len; i++)
    out_value (expr[i]);
  printf ("\n");

  printf ("Express nodes : %d\n", len);
  printf ("--------------------\n");
}

/* get priority level */
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
			    }
			  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
			}
		      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;
}

/* test mdi_torpn function */
void
test_midtorpn (void)
{
  int len = 0, rlen = 0;
  Expr expr[128], rpn[128];
  //char *es = "100+200*300+400";
  //char *es = "(100+200)*(300+400)";
  char *es = "100*(300-200)/400";

  len  = parse_string (es, expr, 128);
  rlen = mid_torpn (expr, rpn, len);

  printf ("Express : %s\n", es);
  printf ("--------------------\n");
  for (int i = 0; i < rlen; i++)
    out_info (rpn[i]);

  printf ("--------------------\n");
  printf ("RPN expr:");
  for (int i = 0; i < rlen; i++)
    out_value (rpn[i]);
  printf ("\n");
}

/* 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;
}

/* test compute_rpn_express function */
void
test_compute_rpn_express (void)
{
  int len = 0, rlen = 0;
  Expr expr[128], rpn[128], rs;
  //char *es = "100+200*300+400";
  //char *es = "(100+200)*(300+400)";
  char *es = "100*(300-200)/400";

  len  = parse_string (es, expr, 128);
  rlen = mid_torpn (expr, rpn, len);

  printf ("Express : %s\n", es);
  printf ("--------------------\n");
  for (int i = 0; i < rlen; i++)
    out_info (rpn[i]);

  printf ("--------------------\n");
  printf ("RPN expr:");
  for (int i = 0; i < rlen; i++)
    out_value (rpn[i]);
  printf ("\n");

  printf ("--------------------\n");
  rs = compute_rpn_express (rpn, rlen);
  printf ("--------------------\n");
  printf (" Result : %ld\n", rs.V.ival);
}

/* evalute express */
void
eval_express (void)
{
  Expr expr[128], rpn[128], rs;
  char es[1024] = {0};
  int idx = 0, len = 0, rlen = 0;
  char c;

  printf ("REPL:> ");
  c = fgetc (stdin);
  while (c != EOF)
    {
      if (c == '\n')
	{
	  len  = parse_string (es, expr, 128);
	  rlen = mid_torpn (expr, rpn, len);
	  printf ("------------------------------\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 ("REPL:> ");
	  c = fgetc (stdin);
	}
      else
	{
	  es[idx] = c;
	  idx++; c = fgetc (stdin);
	}
    }
}

/**/
int
main (int argc, char *argv[])
{
  //test_pstring ();
  //test_midtorpn ();
  //test_compute_rpn_express ();
  eval_express ();
  return 0;
}
/******(X(X)X)******/
  • 下一步继续研究数据结构和算法!!!

http://www.kler.cn/a/404347.html

相关文章:

  • 七、电机三环控制
  • Android智能座舱,视频播放场景,通过多指滑屏退回桌面,闪屏问题的另一种解法
  • STM32与CS创世SD NAND(贴片SD卡)结合完成FATFS文件系统移植与测试是一个涉及硬件与软件综合应用的复杂过程
  • Vue 专属状态管理库Pinia的使用与实践
  • Target-absent Human Attention
  • 【Rabbitmq篇】RabbitMQ⾼级特性----消息确认
  • Vue前端开发子组件向父组件传参
  • CTFHub-hate_php
  • 学习C#中的BackgroundWorker 组件
  • 贴贴,一款windows剪切板管理软件
  • std::weak_ptr应用于观察者模式的示例
  • 点亮创新之光:常用缺陷检测算法原理、介绍与发文突破方向全解
  • 持续集成与持续部署:CI/CD实现教程
  • C#之WPF的C1FlexGrid空间的行加载事件和列事件变更处理动态加载的枚举值
  • QT实现列表通过向上向下翻页按钮翻页,以及上下键逐行显示文本行,向左向右键翻页功能
  • 图论之最小生成树计数(最小生成树的应用)
  • 使用API有效率地管理Dynadot域名,删除账户中的whois联系人信息
  • 在 Linux 中,重启命令reboot
  • Linux 用户管理
  • Python简介以及解释器安装(保姆级教学)
  • 一文解读数据仓库的分层逻辑和原理
  • 【Linux从青铜到王者】Linux进程间通信(一)——待完善
  • Python设计模式详解之1 —— 单例模式
  • 例题10-4 冒泡排序 字符串排序
  • Web3游戏先锋 Big Time Studios 重磅推出 $OL 通证,赋能 Open Loot 游戏平台
  • Centos 7 安装 Docker 最新版本