无名之辈-视觉脚本编译器开发(二)

无名之辈-视觉脚本编译器开发

为了实现脚本编译器的常规功能,在上一篇文章中的视频也有展示:新建一个变量(参数名称以及赋值、图片名称以及赋值等等),也包含变量计算(加、减、乘、除、括号优先、公式计算等),也需要常规逻辑运算符(if,for,switch)等。这三个基础造就了一个脚本是否可以独立于编译器使用,(例如:如果不能编译后新建变量则必须在编译前将所有变量名变量类型预设完成,这必然是不可能实现独立脚本化的)。本文就针对可以独立脚本化的问题展开讨论。


本文针对遇到的问题以及相关及解决方式进行的深入讨论,相关源代码暂时不公开。


前言

针对开头所提出的新建变量、变量计算、逻辑运算的问题一下分别进行讨论。


一、如何新建变量

1.引入方法

新建变量名在程序编译之后进行是肯定不可能的,但是变量名的具体含义是什么?比如我叫康博,“康博”这个人名在我的人生中代表什么含义,在社会中有什么意义,在众多物种里又有什么价值?

阅读到这里我们就会进入一个深思,如果所有的人出生不需要名字,是不是社会也可以运转,答案当然是肯定的。但是前提是所有人在出生的时候就被分配了固定的“地址”,该地址是按照一定的规则编码,当我需要Call这个人的时候就能够通过地址偏移去索引到他,这样的访问方式我们一般通称为指针,没错我们可以使用指针来解决这个问题。

指针在C语言中有很多身份,在CPP(C++)中也是一样的。如(指针、数组、链表、堆栈、等),如果我现在有一个变量,我需要去声明它是Int类型,比如:int a=100; 这个在C语言或者CPP语言编译之前是非常容易实现的,几乎有手就能够完成,但是在编译之后怎么实现?

我现在有一个指针,这个指针被声明为QString(字符串)类型作为变量名的存储索引,另外有一个指针,这个指针被声明为int类型,如果第一个指针的指向不为空则我认为第二个指针指向地址的内容有效,则我以int的方式读取第二个指针地址的内容,则实现了一个为int类型变量的声明。
指针

2.变量类型复杂化

当我们能够为一个Int类型变量声明的时候,我们就贪心了起来,是否我能找到一种通用指针类型,可以肆意的往里面存放数据,这个数据是Int、Float、String、Double、Char、Bool…。这个改如何实现?

首先我们在学习计算机语言的时候知道,一个数据是什么类型,计算机就会分配多少的内存,比如Bool=1bit,Byte=8bit、int=16bit、double=32bit等。所以固化思维去寻找能够通用的指针是肯定不行的,那么我们就要变向思考,既然变量类型是前人设计出来的,我们是否也可以顺延已有的变量规则去创建新的类型。答案肯定是可以的。

我们现在要创建一个可以“自由指向”类型的变量,并且和上文一样是编译后生成的,该怎么做呢?当然还是依附于指针,我们需要先创建一个可以指向变量名的指针,也是QString类型QString Name = " ";

根据我们学习C语言的习惯,我们在使用不同数据的时候会以相应的赋值方式进行内容填充,如:

bool a = 0;//或 /1/true/false/True/False;
int a = 100;//
float a =1.11;//
char a = 'A';//
string a = "abcdefg";//

按照这样的逻辑,我们可以将所有的值转化为最复杂的那个,然后通过判断值的内容来取出我们要的信息出来,这就是第二个指向参数值的指针,也用QString:QString Value = " ";

说明:如果是字符串类型,则 " 符号有且只有2个,如果是char类型,则 ’ 符号有且只有2个,如果是float类型,则 . 符号有且只有1个,如此这般即可。比如我们还可以增加更多的信息,将变量设定为同类型数组、变量加上“.L”则返回数组长度,自定义“Pi”返回值为3.1415926。等等

3.变量长度自由化

当提到指针的长度或者变量的长度,有的朋友很快就联想到了指针数组化,用数组来代替指针就可以实现多数据保存。这是很聪明的想法,但是在程序使用过程中没有办法“自由化”。什么是长度自由化,即长度可以长可以短,这就是上文有提到的“链表”的优点。

链表的使用是只需要定义入口,不需要定义长度的。在内存上的实现方式是游离态、自由态。即链表在申请的时候是随申请随创建,他的数据可能存在于用户内存的任何位置,是程序员无法通过绝对地址寻访的,这就形成了一个弊端,当链表长达几万个内容的时候,他的运行速度是不如数组快的(当然,一个脚本的单条链表数据长达几万个,这个脚本也应该优化了)。

度娘的解释

QStringList  Name ;
QStringList  Value ;

Name.Clear();
Value.Clear();

二、变量计算

1.最简单逻辑计算

实现最小逻辑计算的基础:输入参数类型,输出参数类型
在自己的逻辑计算里面不可避免的会遇到精度丢失问题,如:输入float,输出int,在这种情况下程序编撰者可以定义规则,是“截尾取整”还是“四舍五入”,我的实现方式是截尾取整,因为四舍五入还有更复杂的一个问题,从第几位开始判断四舍五入,如:3.445;最终结果是4,不如结果就是3看着有逻辑感。

根据上文“变量类型复杂化”中可以通过变量内容得知当前要参与计算的变量A与变量B的类型。通过加减乘除运算返回一个“最大”类型,通过输出参数类型要求“修剪”为所需要的类型即可。

void ReturnValue(QString A,QString B,QString C,char D){//AB为输入,C为输出,这都是变量名,D为符号
	switch(D)
	case '+':{
		WritePar(C,ReadPar(A)+ReadPar(B));
	}
	...
	void WritePar(QString ParName,QString Parvalue);
	bool ReadPar(QString ParName);
	char ReadPar(QString ParName);
	int ReadPar(QString ParName);
	float ReadPar(QString ParName);
}

2.复杂的逻辑计算

复杂的逻辑计算主要是处理公式,如:ParA*(ParB+ParC*(ParD+(ParE/ParF)-ParG)); 这样的公式。这种公式有一不好处理的地方,就是并不知道括号嵌套了多少个。

如何处理多层括号嵌套?这里建立一个数学模型,金字塔式解析方式。如图:
金字塔式分解公式
金字塔的入口是公式,金字塔的出口是一个值,金字塔的上升和下降都是靠“(” / “)”实现的,金字塔的每一层都是一样的函数。如果达到了这样的效果,一个合理的公式将被迎刃而解。
举例:

QString Function(QString fun){
	QString result;
	if(fun.at(0) == '('){//判断当前字符串首尾是否为左括号
		fun = Function(fun.mid(1));//上升金字塔台阶,函数自我调用
	}
	else if(fun.at(0) == ')'){
		return result; //下降金字塔台阶,函数返回内容
	}
	else{
		//处理无括号后的内容,需按照优先乘除后加减编写。
	}

}

复杂的公式计算便可以脚本化运行起来。


总结

篇幅有限,第三个问题我们放到下一次讨论。
万年不变结尾:以上仅代表本人在这个行业、这个岗位的个人看法。以及针对遇到的此种问题提出的个人建议,不代表公司以及社会任何组织的任何利益或行为。本文所使用的所有库文件皆可追溯,若有侵权可联系本人(WeChat:Conbo_iwork)删除帖子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Conbo-biubiubiu

若于君有益,锱铢亦是动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值