首页 > 其他分享 >C语言之实现简单的表达式计算器

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

时间:2024-11-20 11:45:30浏览次数:3  
标签:expr ip printf st 计算器 oval ival 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)******/
  • 下一步继续研究数据结构和算法!!!

标签:expr,ip,printf,st,计算器,oval,ival,C语言,表达式
From: https://blog.csdn.net/gwsong52/article/details/143831872

相关文章

  • 正则表达式制作表单javascript
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=d......
  • c语言if else结构
    c语言if语句如何使用内部是一个判断真假的条件语句,如果该语句为真,就执行其下的一条语句。若有多条语句则应用花括号括起来算作一条语句。一般if和else连用。就是说,满足if条件就执行这个,否则就执行else下的语句。if是c语言的关键字,所有c语言的基本语句都是有编译器(比如VC,GCC......
  • c语言初学者练习——指针进阶学习
    c语言初学者练习——结构体一、字符指针在指针的类型中有一种指针类型为字符指针:char*字符指针的一般使用方法:intmain(){ chara='w'; char*pc=&a; *pc='b'; printf("%c",a); return0;}另一种使用方法:把字符串首字符a的地址赋值给了p,但不安全VS......
  • 【C语言】操作符2(含操作符的应用)
    1、单目操作符    单目操作符有下面几种:    !、++、--、&(取地址)、*(指针)、+(正号)、-(负号)、~、sizeof、(类型)    其中就还有&和*操作符还没有学习过,这个我们在后面学习指针的时候会详细来讲的。2、逗号表达式    逗号表达式就是用逗号隔开的......
  • c语言分支循环语句
    大家好!今天为大家带来的是有关分支与循环语句的相关内容,希望对您有所帮助。正文如下:众所周知,c语言是结构化的程序设计语言,其中的结构化就体现在对于三大基本结构的多元化使用,而这三大结构分别是:顺序结构,选择结构,循环结构通过对三大结构的学习,我们就可以掌握c语言程序的简单......
  • c语言中const参数莫名警告
     001、[root@PC1test1]#lstest.c[root@PC1test1]#cattest.c##测试c程序#include<stdio.h>voidprint_array(constintx[4][3]);//函数原型声明intmain(void){inta[4][3]={{1,2,4},{2,1,4},{2,5,1},{4,2,3}};......
  • C语言分支和循环相关游戏
    文章目录猜数字游戏1随机数生成1.1rand1.2srand1.3time1.4设置随机数的范围2.猜数字游戏实现猜数字游戏游戏要求:电脑自动生成1~100的随机数玩家猜数字,猜数字的过程中,根据猜测数据的大小给出大了或小了的反馈,直到猜对,游戏结束1随机数生成如何产生随机数,一......
  • 2024/11/19日 日志 数据结构实验(2)---栈实现表达式求值、队列应用(蓝桥杯)
    栈实现表达式求值问题:https://pintia.cn/problem-sets/1858366427985383424/exam/problems/type/7?problemSetProblemId=1858366732315615232解答:点击查看代码#include<bits/stdc++.h>usingnamespacestd;//运算符优先级intprecedence(charop){switch(op){......
  • C++ Lambda表达式笔记
    1.什么是Lambda表达式?Lambda表达式是C++11引入的一种特性,允许定义匿名函数(没有名字的函数),并且可以像普通函数一样调用,甚至可以作为参数传递给其他函数。基本语法:[capture_list](parameters)->return_type{function_body};[capture_list]:捕获列表,决定外部变量如何......
  • 经典C语言代码——part 2
    【程序4】题目:输入某年某月某日,判断这一天是这一年的第几天?1.程序分析:以3月5日为例,应该先把前两个月的加起来,然后再加上5天即本年的第几天,特殊情况,闰年且输入月份大于3时需考虑多加一天。2.程序源代码:main(){intday,month,year,sum,leap;printf("\nplease......