Perl实现逆波兰式与递归计算

4 篇文章 0 订阅
1 篇文章 0 订阅

  近一个学期都没有写过博客了,甚至CSDN也很少来了,有点想念这里了。大三忙的比高三还累,早八点出,晚十二点归,弄得自己都不知道是在读大学还是在工作。另一方面兴趣也逐渐转移了,对纯软件没有以前那样着迷,喜欢搞点基于ARM和FPGA的嵌入式系统,这一个学期都在实验室帮老板写支持FPGA多个部分可重构的操作系统,得从硬件到汇编到驱动到操作系统一层一层学,累呛了。 实验室里面的研究生学长谈了半年的找工作的事了,见面就是offer与面试的,听的出来似乎这几年行情不是很好,找工作压力挺大的。高不成低不就吧,有大牛拿到微软的offer,也有人转到金融了,还有转咨询的,年薪都超过12万的,反正最后哪行年薪高就去哪了。

或许这就是世俗所说的一切向钱看吧,读了二十年的书当然希望过的好些。这学期上了一门课:perl程序设计,老师是清华过来的博士后,人相当不错,不得不说清华出来的素质还是很高的。老师除了上课,还会趁着我们价值观成熟之前,给我们普及一些积极正面的东西。他总戏谑说自己在原来那个班级里面算个loser了,其他同学去金融的、公务员的、国外的都混得比他好多了,当初在清华其实他也是有机会拿到一个相当不错的公务员职位的,但是他拒绝了,选择继续走科研这条loser路。他说他从来没有后悔过,因为在这个世俗的社会里,他并没有浪费人生在各种应酬、附炎趋势、虚伪与勾心斗角当中,他说“至少现在我依然在做我喜欢做的事情”。 

其实我想我也是,进大学以来,虽然绩点不算高,出国直研不太方便,奖学金没拿过,也没妹子,自甘寂寞;但是我也一直在做我喜欢做的事情:用软件和硬件DIY,实现自己的想法。我没有花大把时间与班里的学霸不择手段的争夺那几个A,没有花大把时间在各种学生会里腐败、做假账,也没有花大把时间水人人或者哄几个无聊的女生开心,也不是dota男;而是每天泡在图书馆与实验室里。不得不说是苦逼的日子了,但是欣慰的是我也依然在做我喜欢做的事情,而且哥在实验室可能要弄到妹子了哦,呵呵。

  不抱怨了,说说perl的事情吧。其实心里开始挺排斥Perl,因为Perl毕竟还是脚本语言,感觉跟Javascript差不多,而且写起来很难看。但是一个学期学下来,发现Perl相比C++在很多方面还是很优秀的,尤其是Perl对正则表达式的支持特别好,而且区别于Js,Perl能在正则表达式里面调用函数,处理文本相当的带劲。在实验室处理网表文件都得靠Perl来做。

不仅如此,Perl的动态性性也特好,支持tied功能,能够对任何变量的行为重新定义,就感觉perl就是自己编出来的;符号引号动态创建代码之类的都很方便;还有就是perl的package 模块确实是我用过的最方便移植的,在CPAN里面找到别人的模块再直接用,别C++里面调用别人的库还是要方便不少。总体上说,perl不太适合团队合作中使用,因为不太好维护,但对于个人使用起来还是特别好用的。

  事先逆波兰式与递归其实还是挺简单的,毕竟算法不复杂。其实用perl写出来与应C写起来差不多了,就是perl与C两者在内存模型方面差别太大了,perl没有指针的都是用“引用”,实现任意维数的数据类型很方便,而且不需要事先声明。

算法百度百科里面如下:

一般算法

  将一个普通的中序表达式转换为逆波兰表达式的一般算法是:
  (1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
  (2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
  (3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
  (4)如果不是数字,该字符则是运算符,此时需比较优先关系。
  做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。
  (5)重复上述操作(3)-(4)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。

代码还是写在下面,虽然perl代码不太好看,但应该还是还能看懂的,直接复制下来就能跑的,希望对刚学perl的筒子们有用。

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
while(1){
	my $data=&get_input();
	if(!$data){
		print "your expr is illegal,please check it\n";next;
	}
	my @tree=&get_tree($data);
	print "The tree is: \n", Dumper(@tree)," \n";
	my $result=&count($tree[0]);
	print "The result of the expr is: $result\n";
}
 ######获得输入数据函数
sub get_input{
	print "Input your expr>>";
	chomp( my $inputdata=<STDIN>);
	$inputdata=~s/\s//g;   #去除所有的空白符
	if(!$inputdata){exit;}
	if($inputdata=~/[a-zA-Z\.]/)   { #做简单检查是否存在小数或者字符出现
		return 0;}
	$inputdata=join("",$inputdata,"#") if (substr($inputdata,length($inputdata)-1,1) ne "#"); #在最后补#
}
#get the tree of the expr
sub get_tree{
	my $data=pop;
	my ($stop,$top,$ch,@stack,@tree);
	$top=0;$stack[0]='#';
	while($top<length($data)){
		$ch=substr($data,$top,1);
		if($ch eq "+" or $ch eq "-"){
			my $op=pop(@stack);
			if($op eq '#' or $op eq '('  or  $op eq '['  or $op eq '{'){
				push(@stack,$op);push(@stack,$ch);}
			else{
				 push(@stack,$op);
				while(1){
					my $op=pop(@stack);
                    if($op eq '#' or $op eq '(' or $op eq '[' or $op eq '{'){
						push(@stack,$op);push(@stack,$ch); last;}
					else{
						my @node;
						push(@node,$op);push(@node,pop(@tree));
						push(@node,pop(@tree));push(@tree,[@node]);
					}
				}
			}
			$top=$top+1; next;
		}
		if($ch eq "*"  or $ch eq "/")
		{
			my $op=pop(@stack);
			if($op ne "*" and $op ne "/"){
				push(@stack,$op);push(@stack,$ch);}
			else{
				push(@stack,$op);
				while(1){
					my $op=pop(@stack);
					if($op ne "*" and $op ne "/"){
						push(@stack,$op);push(@stack,$ch);last;}
					else	{
						my @node;
						push(@node,$op);push(@node,pop(@tree));
						push(@node,pop(@tree));push(@tree,[@node]);
					}
				}
			}
			$top=$top+1;next;
		}
		if($ch eq '(' or $ch eq '{' or $ch eq '['){
			push(@stack,$ch);$top=$top+1;next;
		}
		if($ch eq ')' or $ch eq ']' or $ch eq '}'){
			while(1){
              my $op=pop(@stack);
			  if($op eq '('  or $op eq '['  or $op eq '{'){
				  last;}
             my @node;
			 push(@node,$op); push(@node,pop(@tree));
			 push(@node,pop(@tree)); push(@tree,[@node])
			}
			 $top=$top+1;next;
		}
		if($ch eq '#'){
			while(1){
				my $op=pop(@stack);
				if($op eq '#'){
					last;}
				else{
					my @node;
					push(@node,$op);push(@node,pop(@tree));
					push(@node,pop(@tree));push(@tree,[@node]);
				}
			}
			$top=$top+1;next;
		}
		if($ch ge '0' and $ch le '9'){
			my $num=0;
			while($ch ge '0' and $ch le '9'){
				$num=$num*10+$ch; $top=$top+1;
				$ch=substr($data,$top,1);
			}
		  push(@tree,$num);	 next;
		}
		else{
			$top=$top+1;
		}
	}
     return reverse  @tree;
}

#####检查是否为引用
sub judge_digit
{
	my $data=shift;
	if(ref($data) eq "ARRAY"){
		return 0;}
	else{
		return 1;}
}
#####根据树计算最终结果
########利用递归函数实现
sub count
{
	my $x=shift;
	my @data=@{$x};
    if(judge_digit($data[1])==0){
		$data[1]=count($data[1]);
	}
	if(judge_digit($data[2])==0){
		$data[2]=count($data[2]);
	}
	if($data[0] eq "+"){
        return $data[1]+$data[2];
	}elsif($data[0] eq "-") {
         return $data[2]-$data[1];
	}elsif($data[0] eq "*"){
         return $data[1]*$data[2];
	}elsif($data[0] eq "/") {
         return $data[2]/$data[1];
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值