12 个解决方案
#1
搜一下“用栈实现表达式求值”。
这是数据结构和算法课程中比较基础的内容,主要思路是用两个堆栈,一个用来存储操作符,一个存储操作数,从字符串中解析出一个元素(数或运算符),通过运算符之间的优先级,控制操作符进栈出栈。出栈是指的弹出两个操作数一个运算符,然后将它们的运算结果再次入栈。直到字符串和两个栈全部为空。
这是数据结构和算法课程中比较基础的内容,主要思路是用两个堆栈,一个用来存储操作符,一个存储操作数,从字符串中解析出一个元素(数或运算符),通过运算符之间的优先级,控制操作符进栈出栈。出栈是指的弹出两个操作数一个运算符,然后将它们的运算结果再次入栈。直到字符串和两个栈全部为空。
#2
public static object Eval(string AExpression)
{
try
{
return new DataTable().Compute(AExpression, "");
}
catch
{
return null;
}
}
#3
楼上有个问题,乘方在C#可不是这么表示阿,四则运算楼上是对的
#4
那是VB的语法。
#5
这个应该可以满足你的基本要求!!
#include <stdio.h>
#include <stdlib.h>
#define init_size 10
#define pp_size 2
int i=0;
typedef struct
{char *base;
char *top;
int size;
}optr;
typedef struct
{int *base;
int *top;
int size;
}oped;
char lable[8][8]={' ','+','-','*','/','(',')','#',
'+','>','>','<','<','<','>','>',
'-','>','>','<','<','<','>','>',
'*','>','>','>','>','<','>','>',
'/','>','>','>','>','<','>','>',
'(','<','<','<','<','<','=',' ',
')','>','>','>','>',' ','>','>',
'#','<','<','<','<','<',' ','='
};
void init_oped(oped *s)
{s->base=(int *)malloc(init_size*sizeof(int));
if(!s->base) {printf("init error!");exit(0);}
s->top=s->base;
s->size=init_size;
}
void init_optr(optr *s)
{s->base=(char *)malloc(init_size*sizeof(char));
if(!s->base) {printf("init error!");exit(0);}
s->top=s->base;
s->size=init_size;
}
void push_oped(oped *s,int e)
{if(s->top-s->base>=s->size)
{s->base=(int *)realloc(s->base,(init_size+pp_size)*sizeof(int));
if(!s->base) {printf("puss_oped error!");exit(0);}
s->top=s->base+s->size;
s->size+=pp_size;
}
*s->top=e;
s->top++;
}
void push_optr(optr *s,char e)
{if(s->top-s->base>=s->size)
{s->base=(char *)realloc(s->base,(init_size+pp_size)*sizeof(char));
if(!s->base) {printf("push_optr error!");exit(0);}
s->top=s->base+s->size;
s->size+=pp_size;
}
*s->top=e;
s->top++;
}
char pop_optr(optr *s)
{char ch;
if(s->top==s->base) {printf("optr-stack NULL!");exit(0);}
ch=*(--s->top);
return ch;
}
int pop_oped(oped *s)
{int ch;
if(s->top==s->base) {printf("oped-stack NULL!");exit(0);}
ch=*(--s->top);
return ch;
}
char gettop(optr *s)
{char ch;
if(s->top==s->base) {printf("gettop stack NULL error!");exit(0);}
ch=*(s->top-1);
return ch;
}
char precede(char x,char y)
{char ch;
int i,j;
for(i=0;i<8;i++)
if(lable[i][0]==x) break;
for(j=0;j<8;j++)
if(lable[0][j]==y) break;
ch=lable[i][j];
return ch;
}
int operate(int x,char ch,int y)
{int sum=0;
switch (ch)
{case '+':sum=x+y;break;
case '-':sum=x-y;break;
case '*':sum=x*y;break;
case '/':sum=x/y;break;
}
return sum;
}
main()
{optr *p;
oped *s;
char ch,op;
int sum=0,temp,a,b;
init_optr(p);push_optr(p,'#');
init_oped(s);
printf("\nplease enter :");
ch=getchar();
while(ch!='#'||(op=gettop(p))!='#')
{if(ch>='0'&&ch<='9')
{sum=sum*10+(ch-'0');ch=getchar();}
else {push_oped(s,sum);
sum=0;
A1: switch (precede(gettop(p),ch))
{case '<':push_optr(p,ch);ch=getchar();break;
case '=':if(ch=='#') break;
else {pop_optr(p);
ch=getchar();
break;}
case '>':{b=pop_oped(s);op=pop_optr(p);a=pop_oped(s);
temp=operate(a,op,b);
push_oped(s,temp);
goto A1;
}
}
}
}
printf("\ncomeout:%d",pop_oped(s));
}
#include <stdio.h>
#include <stdlib.h>
#define init_size 10
#define pp_size 2
int i=0;
typedef struct
{char *base;
char *top;
int size;
}optr;
typedef struct
{int *base;
int *top;
int size;
}oped;
char lable[8][8]={' ','+','-','*','/','(',')','#',
'+','>','>','<','<','<','>','>',
'-','>','>','<','<','<','>','>',
'*','>','>','>','>','<','>','>',
'/','>','>','>','>','<','>','>',
'(','<','<','<','<','<','=',' ',
')','>','>','>','>',' ','>','>',
'#','<','<','<','<','<',' ','='
};
void init_oped(oped *s)
{s->base=(int *)malloc(init_size*sizeof(int));
if(!s->base) {printf("init error!");exit(0);}
s->top=s->base;
s->size=init_size;
}
void init_optr(optr *s)
{s->base=(char *)malloc(init_size*sizeof(char));
if(!s->base) {printf("init error!");exit(0);}
s->top=s->base;
s->size=init_size;
}
void push_oped(oped *s,int e)
{if(s->top-s->base>=s->size)
{s->base=(int *)realloc(s->base,(init_size+pp_size)*sizeof(int));
if(!s->base) {printf("puss_oped error!");exit(0);}
s->top=s->base+s->size;
s->size+=pp_size;
}
*s->top=e;
s->top++;
}
void push_optr(optr *s,char e)
{if(s->top-s->base>=s->size)
{s->base=(char *)realloc(s->base,(init_size+pp_size)*sizeof(char));
if(!s->base) {printf("push_optr error!");exit(0);}
s->top=s->base+s->size;
s->size+=pp_size;
}
*s->top=e;
s->top++;
}
char pop_optr(optr *s)
{char ch;
if(s->top==s->base) {printf("optr-stack NULL!");exit(0);}
ch=*(--s->top);
return ch;
}
int pop_oped(oped *s)
{int ch;
if(s->top==s->base) {printf("oped-stack NULL!");exit(0);}
ch=*(--s->top);
return ch;
}
char gettop(optr *s)
{char ch;
if(s->top==s->base) {printf("gettop stack NULL error!");exit(0);}
ch=*(s->top-1);
return ch;
}
char precede(char x,char y)
{char ch;
int i,j;
for(i=0;i<8;i++)
if(lable[i][0]==x) break;
for(j=0;j<8;j++)
if(lable[0][j]==y) break;
ch=lable[i][j];
return ch;
}
int operate(int x,char ch,int y)
{int sum=0;
switch (ch)
{case '+':sum=x+y;break;
case '-':sum=x-y;break;
case '*':sum=x*y;break;
case '/':sum=x/y;break;
}
return sum;
}
main()
{optr *p;
oped *s;
char ch,op;
int sum=0,temp,a,b;
init_optr(p);push_optr(p,'#');
init_oped(s);
printf("\nplease enter :");
ch=getchar();
while(ch!='#'||(op=gettop(p))!='#')
{if(ch>='0'&&ch<='9')
{sum=sum*10+(ch-'0');ch=getchar();}
else {push_oped(s,sum);
sum=0;
A1: switch (precede(gettop(p),ch))
{case '<':push_optr(p,ch);ch=getchar();break;
case '=':if(ch=='#') break;
else {pop_optr(p);
ch=getchar();
break;}
case '>':{b=pop_oped(s);op=pop_optr(p);a=pop_oped(s);
temp=operate(a,op,b);
push_oped(s,temp);
goto A1;
}
}
}
}
printf("\ncomeout:%d",pop_oped(s));
}
#6
// SuperCalc.cs - 超级计算器
using System;
using System.Windows.Forms;
using System.CodeDom.Compiler;
using Microsoft.VisualBasic;
using System.Reflection;
using System.Text;
using System.Globalization;
namespace Skyiv
{
class SuperCalc : Form
{
TextBox tbxA1;
TextBox tbxA3;
[STAThread]
static void Main(string [] args)
{
Application.Run(new SuperCalc());
}
SuperCalc()
{
Text = "Super Calculator";
StartPosition = FormStartPosition.CenterScreen;
Width = 300;
Height = 300;
tbxA1 = new TextBox();
tbxA1.Parent = this;
tbxA1.Multiline = true;
tbxA1.WordWrap = false;
tbxA1.Dock = DockStyle.Fill;
tbxA1.BorderStyle = BorderStyle.FixedSingle;
Panel pnlA1 = new Panel();
pnlA1.Parent = this;
pnlA1.Height = 22;
pnlA1.Dock = DockStyle.Top;
tbxA3 = new TextBox();
tbxA3.Parent = pnlA1;
tbxA3.Dock = DockStyle.Fill;
tbxA3.BorderStyle = BorderStyle.FixedSingle;
tbxA3.ReadOnly = true;
Button btnA3 = new Button();
btnA3.Text = "&Calculate";
btnA3.Parent = pnlA1;
btnA3.Width = 80;
btnA3.Dock = DockStyle.Left;
btnA3.Click += new EventHandler(Calc_Clicked);
}
void Calc_Clicked(object sender, EventArgs ea)
{
(sender as Control).Enabled = false;
try
{
tbxA3.Text = (new Expression(tbxA1.Text)).Compute().ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
finally
{
(sender as Control).Enabled = true;
}
}
}
// VBExpression.cs - 动态生成数学表达式并计算其值
// 表达式使用 Visual Baisc 语法
// 可使用 pi、e 等常量,sin、cos、tan、log、sqrt 等函数
sealed class Expression
{
object instance;
MethodInfo method;
public Expression(string expression)
{
if (expression.ToUpper(CultureInfo.InvariantCulture).IndexOf("RETURN") < 0)
{
expression = "Return " + expression.Replace(Environment.NewLine, " ");
}
string className = "Expression";
string methodName = "Compute";
CompilerParameters p = new CompilerParameters();
p.GenerateInMemory = true;
CompilerResults cr = new VBCodeProvider().CompileAssemblyFromSource
(
p,
string.Format
(
@"Option Explicit Off
Option Strict Off
Imports System, System.Math, Microsoft.VisualBasic
NotInheritable Class {0}
Public Function {1} As Double
{2}
End Function
End Class",
className, methodName, expression
)
);
if(cr.Errors.Count > 0)
{
string msg = "Expression(\"" + expression + "\"): \n";
foreach (CompilerError err in cr.Errors) msg += err.ToString() + "\n";
throw new Exception(msg);
}
instance = cr.CompiledAssembly.CreateInstance(className);
method = instance.GetType().GetMethod(methodName);
}
public double Compute()
{
return (double)method.Invoke(instance, null);
}
}
}
#7
#8
http://www.google.com/search?q=4*36%2B7%2B88%2F12%5E2&hl=zh-CN&newwindow=1&lr=&nxpt=20.39471539279207923300
(4 * 36) + 7 + (88 / (12^2)) = 151.611111
(4 * 36) + 7 + (88 / (12^2)) = 151.611111
#9
很好很强大~~
#10
难道net框架里就没有解决这个问题的类?
#11
mark
慢慢看
慢慢看
#12
果然是无敌方法!!!——在效率方面:
DataTable 的 Compute() 在计算时:速度特别快!——基本的加减法几乎不消耗时间
楼主的:
Expression 的 Compute() 在计算时:速度都保持在 300 毫秒 左右!——基本的加减法也消耗这么多的时间:估计是在 编译时浪费了时间;
——但是,不容否认:Expression 真的很无敌.....
#1
搜一下“用栈实现表达式求值”。
这是数据结构和算法课程中比较基础的内容,主要思路是用两个堆栈,一个用来存储操作符,一个存储操作数,从字符串中解析出一个元素(数或运算符),通过运算符之间的优先级,控制操作符进栈出栈。出栈是指的弹出两个操作数一个运算符,然后将它们的运算结果再次入栈。直到字符串和两个栈全部为空。
这是数据结构和算法课程中比较基础的内容,主要思路是用两个堆栈,一个用来存储操作符,一个存储操作数,从字符串中解析出一个元素(数或运算符),通过运算符之间的优先级,控制操作符进栈出栈。出栈是指的弹出两个操作数一个运算符,然后将它们的运算结果再次入栈。直到字符串和两个栈全部为空。
#2
public static object Eval(string AExpression)
{
try
{
return new DataTable().Compute(AExpression, "");
}
catch
{
return null;
}
}
#3
楼上有个问题,乘方在C#可不是这么表示阿,四则运算楼上是对的
#4
那是VB的语法。
#5
这个应该可以满足你的基本要求!!
#include <stdio.h>
#include <stdlib.h>
#define init_size 10
#define pp_size 2
int i=0;
typedef struct
{char *base;
char *top;
int size;
}optr;
typedef struct
{int *base;
int *top;
int size;
}oped;
char lable[8][8]={' ','+','-','*','/','(',')','#',
'+','>','>','<','<','<','>','>',
'-','>','>','<','<','<','>','>',
'*','>','>','>','>','<','>','>',
'/','>','>','>','>','<','>','>',
'(','<','<','<','<','<','=',' ',
')','>','>','>','>',' ','>','>',
'#','<','<','<','<','<',' ','='
};
void init_oped(oped *s)
{s->base=(int *)malloc(init_size*sizeof(int));
if(!s->base) {printf("init error!");exit(0);}
s->top=s->base;
s->size=init_size;
}
void init_optr(optr *s)
{s->base=(char *)malloc(init_size*sizeof(char));
if(!s->base) {printf("init error!");exit(0);}
s->top=s->base;
s->size=init_size;
}
void push_oped(oped *s,int e)
{if(s->top-s->base>=s->size)
{s->base=(int *)realloc(s->base,(init_size+pp_size)*sizeof(int));
if(!s->base) {printf("puss_oped error!");exit(0);}
s->top=s->base+s->size;
s->size+=pp_size;
}
*s->top=e;
s->top++;
}
void push_optr(optr *s,char e)
{if(s->top-s->base>=s->size)
{s->base=(char *)realloc(s->base,(init_size+pp_size)*sizeof(char));
if(!s->base) {printf("push_optr error!");exit(0);}
s->top=s->base+s->size;
s->size+=pp_size;
}
*s->top=e;
s->top++;
}
char pop_optr(optr *s)
{char ch;
if(s->top==s->base) {printf("optr-stack NULL!");exit(0);}
ch=*(--s->top);
return ch;
}
int pop_oped(oped *s)
{int ch;
if(s->top==s->base) {printf("oped-stack NULL!");exit(0);}
ch=*(--s->top);
return ch;
}
char gettop(optr *s)
{char ch;
if(s->top==s->base) {printf("gettop stack NULL error!");exit(0);}
ch=*(s->top-1);
return ch;
}
char precede(char x,char y)
{char ch;
int i,j;
for(i=0;i<8;i++)
if(lable[i][0]==x) break;
for(j=0;j<8;j++)
if(lable[0][j]==y) break;
ch=lable[i][j];
return ch;
}
int operate(int x,char ch,int y)
{int sum=0;
switch (ch)
{case '+':sum=x+y;break;
case '-':sum=x-y;break;
case '*':sum=x*y;break;
case '/':sum=x/y;break;
}
return sum;
}
main()
{optr *p;
oped *s;
char ch,op;
int sum=0,temp,a,b;
init_optr(p);push_optr(p,'#');
init_oped(s);
printf("\nplease enter :");
ch=getchar();
while(ch!='#'||(op=gettop(p))!='#')
{if(ch>='0'&&ch<='9')
{sum=sum*10+(ch-'0');ch=getchar();}
else {push_oped(s,sum);
sum=0;
A1: switch (precede(gettop(p),ch))
{case '<':push_optr(p,ch);ch=getchar();break;
case '=':if(ch=='#') break;
else {pop_optr(p);
ch=getchar();
break;}
case '>':{b=pop_oped(s);op=pop_optr(p);a=pop_oped(s);
temp=operate(a,op,b);
push_oped(s,temp);
goto A1;
}
}
}
}
printf("\ncomeout:%d",pop_oped(s));
}
#include <stdio.h>
#include <stdlib.h>
#define init_size 10
#define pp_size 2
int i=0;
typedef struct
{char *base;
char *top;
int size;
}optr;
typedef struct
{int *base;
int *top;
int size;
}oped;
char lable[8][8]={' ','+','-','*','/','(',')','#',
'+','>','>','<','<','<','>','>',
'-','>','>','<','<','<','>','>',
'*','>','>','>','>','<','>','>',
'/','>','>','>','>','<','>','>',
'(','<','<','<','<','<','=',' ',
')','>','>','>','>',' ','>','>',
'#','<','<','<','<','<',' ','='
};
void init_oped(oped *s)
{s->base=(int *)malloc(init_size*sizeof(int));
if(!s->base) {printf("init error!");exit(0);}
s->top=s->base;
s->size=init_size;
}
void init_optr(optr *s)
{s->base=(char *)malloc(init_size*sizeof(char));
if(!s->base) {printf("init error!");exit(0);}
s->top=s->base;
s->size=init_size;
}
void push_oped(oped *s,int e)
{if(s->top-s->base>=s->size)
{s->base=(int *)realloc(s->base,(init_size+pp_size)*sizeof(int));
if(!s->base) {printf("puss_oped error!");exit(0);}
s->top=s->base+s->size;
s->size+=pp_size;
}
*s->top=e;
s->top++;
}
void push_optr(optr *s,char e)
{if(s->top-s->base>=s->size)
{s->base=(char *)realloc(s->base,(init_size+pp_size)*sizeof(char));
if(!s->base) {printf("push_optr error!");exit(0);}
s->top=s->base+s->size;
s->size+=pp_size;
}
*s->top=e;
s->top++;
}
char pop_optr(optr *s)
{char ch;
if(s->top==s->base) {printf("optr-stack NULL!");exit(0);}
ch=*(--s->top);
return ch;
}
int pop_oped(oped *s)
{int ch;
if(s->top==s->base) {printf("oped-stack NULL!");exit(0);}
ch=*(--s->top);
return ch;
}
char gettop(optr *s)
{char ch;
if(s->top==s->base) {printf("gettop stack NULL error!");exit(0);}
ch=*(s->top-1);
return ch;
}
char precede(char x,char y)
{char ch;
int i,j;
for(i=0;i<8;i++)
if(lable[i][0]==x) break;
for(j=0;j<8;j++)
if(lable[0][j]==y) break;
ch=lable[i][j];
return ch;
}
int operate(int x,char ch,int y)
{int sum=0;
switch (ch)
{case '+':sum=x+y;break;
case '-':sum=x-y;break;
case '*':sum=x*y;break;
case '/':sum=x/y;break;
}
return sum;
}
main()
{optr *p;
oped *s;
char ch,op;
int sum=0,temp,a,b;
init_optr(p);push_optr(p,'#');
init_oped(s);
printf("\nplease enter :");
ch=getchar();
while(ch!='#'||(op=gettop(p))!='#')
{if(ch>='0'&&ch<='9')
{sum=sum*10+(ch-'0');ch=getchar();}
else {push_oped(s,sum);
sum=0;
A1: switch (precede(gettop(p),ch))
{case '<':push_optr(p,ch);ch=getchar();break;
case '=':if(ch=='#') break;
else {pop_optr(p);
ch=getchar();
break;}
case '>':{b=pop_oped(s);op=pop_optr(p);a=pop_oped(s);
temp=operate(a,op,b);
push_oped(s,temp);
goto A1;
}
}
}
}
printf("\ncomeout:%d",pop_oped(s));
}
#6
// SuperCalc.cs - 超级计算器
using System;
using System.Windows.Forms;
using System.CodeDom.Compiler;
using Microsoft.VisualBasic;
using System.Reflection;
using System.Text;
using System.Globalization;
namespace Skyiv
{
class SuperCalc : Form
{
TextBox tbxA1;
TextBox tbxA3;
[STAThread]
static void Main(string [] args)
{
Application.Run(new SuperCalc());
}
SuperCalc()
{
Text = "Super Calculator";
StartPosition = FormStartPosition.CenterScreen;
Width = 300;
Height = 300;
tbxA1 = new TextBox();
tbxA1.Parent = this;
tbxA1.Multiline = true;
tbxA1.WordWrap = false;
tbxA1.Dock = DockStyle.Fill;
tbxA1.BorderStyle = BorderStyle.FixedSingle;
Panel pnlA1 = new Panel();
pnlA1.Parent = this;
pnlA1.Height = 22;
pnlA1.Dock = DockStyle.Top;
tbxA3 = new TextBox();
tbxA3.Parent = pnlA1;
tbxA3.Dock = DockStyle.Fill;
tbxA3.BorderStyle = BorderStyle.FixedSingle;
tbxA3.ReadOnly = true;
Button btnA3 = new Button();
btnA3.Text = "&Calculate";
btnA3.Parent = pnlA1;
btnA3.Width = 80;
btnA3.Dock = DockStyle.Left;
btnA3.Click += new EventHandler(Calc_Clicked);
}
void Calc_Clicked(object sender, EventArgs ea)
{
(sender as Control).Enabled = false;
try
{
tbxA3.Text = (new Expression(tbxA1.Text)).Compute().ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
finally
{
(sender as Control).Enabled = true;
}
}
}
// VBExpression.cs - 动态生成数学表达式并计算其值
// 表达式使用 Visual Baisc 语法
// 可使用 pi、e 等常量,sin、cos、tan、log、sqrt 等函数
sealed class Expression
{
object instance;
MethodInfo method;
public Expression(string expression)
{
if (expression.ToUpper(CultureInfo.InvariantCulture).IndexOf("RETURN") < 0)
{
expression = "Return " + expression.Replace(Environment.NewLine, " ");
}
string className = "Expression";
string methodName = "Compute";
CompilerParameters p = new CompilerParameters();
p.GenerateInMemory = true;
CompilerResults cr = new VBCodeProvider().CompileAssemblyFromSource
(
p,
string.Format
(
@"Option Explicit Off
Option Strict Off
Imports System, System.Math, Microsoft.VisualBasic
NotInheritable Class {0}
Public Function {1} As Double
{2}
End Function
End Class",
className, methodName, expression
)
);
if(cr.Errors.Count > 0)
{
string msg = "Expression(\"" + expression + "\"): \n";
foreach (CompilerError err in cr.Errors) msg += err.ToString() + "\n";
throw new Exception(msg);
}
instance = cr.CompiledAssembly.CreateInstance(className);
method = instance.GetType().GetMethod(methodName);
}
public double Compute()
{
return (double)method.Invoke(instance, null);
}
}
}
#7
#8
http://www.google.com/search?q=4*36%2B7%2B88%2F12%5E2&hl=zh-CN&newwindow=1&lr=&nxpt=20.39471539279207923300
(4 * 36) + 7 + (88 / (12^2)) = 151.611111
(4 * 36) + 7 + (88 / (12^2)) = 151.611111
#9
很好很强大~~
#10
难道net框架里就没有解决这个问题的类?
#11
mark
慢慢看
慢慢看
#12
果然是无敌方法!!!——在效率方面:
DataTable 的 Compute() 在计算时:速度特别快!——基本的加减法几乎不消耗时间
楼主的:
Expression 的 Compute() 在计算时:速度都保持在 300 毫秒 左右!——基本的加减法也消耗这么多的时间:估计是在 编译时浪费了时间;
——但是,不容否认:Expression 真的很无敌.....