从零学习表达式树(三)【变量、常量与赋值】

定义变量

ParameterExpression 用来创建变量、变量参数表达式。

在 C# 中,变量分为以下几种类型:

  • 值类型(Value types)
  • 引用类型(Reference types)
  • 指针类型(Pointer types)

一般上,只用到值类型和引用类型,这里不会说到指针类型。

C#的基本值类型有:bool、byte、char、double、float、int、long等(C#中,数组属于引用类型)。

表达式树创建一个有两种方式变量:

ParameterExpression varA = Expression.Variable(typeof(int), "x");
ParameterExpression varB = Expression.Parameter(typeof(int), "y");

区别:

Expression.Variable()表示创建一个变量;

Expression.Parameter()表示创建一个传入参数;

至于使用区别,后面会有很多具体示例可以体会到。

相同点:生成的类型都是 ParameterExpression

实例:

int a; 
ParameterExpression varA = Expression.Variable(typeof(int), "x");
static void Main(string[] args)
{
            // 等同 Test()里的 int b
            ParameterExpression varB = Expression.Parameter(typeof(int), "y");
            Console.ReadKey();
}
public static void Test(int b)
{
            Console.WriteLine(b);
}

引用类型亦是使用相同方法创建变量。

关于引用类型的示例方法,后面会使用到。

定义常量

使用 Expression.Constan() 定义一个常量。

示例:

ConstantExpression constant = Expression.Constant(100);
ConstantExpression constant1 = Expression.Constant(100, typeof(int));

建议使用两个参数的重载方法,这样浏览代码是,能够快速理解,便于查找修改。

赋值

Expression.Assign() 用于给表达式树变量赋值。
常用定义如下

BinaryExpression Assign(Expression left, Expression right);

将右边表达式的值,赋予左边表达式。

为变量赋值:

ParameterExpression a = Expression.Variable(typeof(int), "x");
ConstantExpression constant = Expression.Constant(100, typeof(int));
BinaryExpression assign = Expression.Assign(a, constant);

注意重载方法类型

Console 的常用重载方法有

public static void WriteLine(object value);
public static void WriteLine(float value);
public static void WriteLine(string value);

在使用表达式树时,注意要调用的重载方法,不能被正常代码的隐式转换误导。

int a = 100;
Console.WriteLine(a);
ParameterExpression aa = Expression.Parameter(typeof(int), "a");
BinaryExpression aaa = Expression.Assign(aa, Expression.Constant(100, typeof(int)));
MethodCallExpression method = Expression.Call(null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), aa);
// 如果没有学到过执行表达式树,现在可以先忽略这里
var call = Expression.Block(new ParameterExpression[] { aa }, aaa, method);
Expression<Action> lambda = Expression.Lambda<Action>(call);
lambda.Compile()();

前面输出 变量 a ,系统会进行隐式的类型转换。但是使用表达式树调用方法,要对应类型才行,以便找到正确的重载方法。上面的表达式树调用 Console.WriteLine() 会报如下错误:

System.ArgumentException:“Expression of type 'System.Int32' cannot be used for parameter of type 'System.String' of method 'Void WriteLine(System.String)'
Arg_ParamName_Name”
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VC++ MFC 经典教程 - 基础篇 1.CP_YourFirstWindowsProgram.mp4 10.MFC_GDI_画直线和曲线.mp4 11.MFC_GDI_画椭圆_多边形及其他形状.mp4 12.MFC_GDI_画笔和画刷.mp4 13.MFC_GDI_画文本和字体.mp4 14.MFC_GDI_备用对象和取消选定.mp4 15.MFC_Ruler.mp4 16.MFC_窗口滚动条.mp4 17.MFC_Accel.mp4 18.MFC_Accel(2).mp4 19.MFC_消息框.mp4 2.Windows_编程模型.mp4 20MFC_客户区鼠标消息.mp4 21.MFC_TicTac-1.mp4 22.MFC_TicTac-2.mp4 23.MFC_TicTac-3.mp4 24.MFC_鼠标滚轮.mp4 25.MFC_捕获鼠标.mp4 26.MFC_VisualKB-1.mp4 27.MFC_VisualKB-2.mp4 29.MFC_菜单.mp4 3.MFC_第一个MFC程序设计.mp4 30.MFC_CButton类.mp4 31.MFC_E_FontView-1.mp4 32.MFC_E_FontView-2.mp4 33.MFC_CEdit类.mp4 34.MFC_MyPad.mp4 35.MFC_对话框_静态文本_编辑框.mp4 36.MFC_对话框_访问控件_7种方法_A.mp4 37.MFC_对话框_访问控件_7种方法_B.mp4 38.MFC_对话框_访问控件_7种方法_C.mp4 39.MFC_对话框_复选框_单选钮.mp4 4.MFC_消息映射.mp4 40.MFC_模态对话框.mp4 41.MFC_非模态对话框.mp4 42.MFC_属性表.mp4 43.MFC_公用对话框.mp4 44.MFC_数组类-1.mp4 45.MFC_数组类-2.mp4 46.MFC_CArray.mp4 47.MFC_列表类.mp4 48.MFC_映射类.mp4 49.MFC_类型指针类.mp4 5.MFC_使用向导快速进行MFC程序设计.mp4 50.MFC_CFile.mp4 51.MFC_CArchive.mp4 52.MFC_四个对象四种方法.mp4 53. MFC_Ruler.mp4 54.MFC_Ruler.mp4 55.MFC_Ruler.mp4 56.MFC_SdiSquares.mp4 57.MFC_Scroll_Ruler.mp4 58.MFC_CHtmlView.mp4 59.MFC_CTreeView.mp4 6.MFC_字符集和TEXT宏.mp4 60.MFC_CListView.mp4 61.MFC_MdiSquares.mp4 62.MFC_动态拆分窗口.mp4 63.MFC_ToolBar.mp4 64.MFC_ToolBar_Ex13a.mp4 65.MFC_StatusBar.mp4 66.MFC_StatusBar_Ex13b.mp4 67.MFC_Rebar.mp4 68.MFC_EZPrint.mp4 69.MFC_Print_Bubble.mp4 7.MFC_建立应用程序.mp4 8.MFC_第一个MFC程序设计(不用向导).mp4 9.MFC_Windows_GDI_设备描述表类.mp4 数据结构与算法_C语言 01.swap.mp4 02.BubbleSort.mp4 03.SelecttionSort.mp4 04.顺序查找.mp4 05.C_DS_折半查找.mp4 06.递归.mp4 07递归算法_折半查找.mp4 08.Permutations.mp4 09.插入排序.mp4 10.快速排序.mp4 11.归并排序.mp4 12.顺序栈.mp4 13.顺序队列.mp4 14.链表的基本概念.mp4 15.单链表的基本运算.mp4 16.循环单链表.mp4 17.双向链表.mp4 18.链式栈.mp4 19.链式队列.mp4 20.基数排序.mp4 21..mp4 22.二叉的存储表示与实现.mp4 23.二叉的遍历.mp4 24.二叉查找.mp4 25.红黑.mp4 26.堆.mp4 27.堆排序.mp4 28.哈希表.mp4 29.图_邻接矩阵
这是一个较为复杂的程序,需要涉及到表达式的构建、中序遍历输出、变量赋值表达式求值。下面给出一个示例代码,供参考: ```python class ExpressionTree: def __init__(self, value, left=None, right=None): self.value = value self.left = left self.right = right def is_leaf(self): return self.left is None and self.right is None def read_expre(postfix): stack = [] for token in postfix: if token.isnumeric(): stack.append(ExpressionTree(int(token))) elif token.isalpha(): stack.append(ExpressionTree(token)) else: right = stack.pop() left = stack.pop() stack.append(ExpressionTree(token, left, right)) return stack.pop() def write_expre(root): if root.is_leaf(): return str(root.value) else: left = write_expre(root.left) right = write_expre(root.right) return "({} {} {})".format(left, root.value, right) def assign(root, var_dict): if root.is_leaf(): if isinstance(root.value, str) and root.value.isalpha(): root.value = var_dict.get(root.value, 0) else: assign(root.left, var_dict) assign(root.right, var_dict) def value(root): if root.is_leaf(): return root.value else: left_val = value(root.left) right_val = value(root.right) if root.value == "+": return left_val + right_val elif root.value == "-": return left_val - right_val elif root.value == "*": return left_val * right_val elif root.value == "/": return left_val / right_val elif root.value == "^": return left_val ** right_val ``` 其中,`ExpressionTree`是表达式的节点类,包含了节点的值和左右子。`read_expre`方法接收一个后缀表达式字符串,返回一个表达式的根节点。`write_expre`方法接收一个表达式的根节点,返回一个中缀表达式字符串(带括号)。`assign`方法接收一个表达式的根节点和一个变量字典,将表达式中的变量节点的值替换为字典中对应的值。`value`方法接收一个表达式的根节点,返回表达式的值。 下面给出一些测试代码,供参考: ```python # 构造表达式 postfix = "ab+c*" root = read_expre(postfix) # 输出中缀表达式 infix = write_expre(root) print(infix) # (a + (b * c)) # 变量赋值 var_dict = {"a": 2, "b": 3, "c": 4} assign(root, var_dict) # 表达式求值 result = value(root) print(result) # 14 ``` 这段代码可以处理简单的后缀表达式,但是对于复杂的表达式可能无法正确求值。如果需要支持更多的运算符和函数,需要对程序进行进一步扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值