ruby实现四则计算器(输入优化)

昨天见有人想用RGSS实现一个计算器,于是我想看看逆波兰表达式,找到了一个好博客,于是昨天晚上实现了算法,今天优化了数据输入。

这次实验真正了解了ruby编程的方便,可以直接关心核心算法部分。这次对正则表达式的用法也加深了。

参考的资料

前缀、中缀、后缀表达式    讲的很清晰

正则表达式分组、断言详解   解决了使用断言的问题


# -*- coding:utf-8 -*-
=begin
中缀表达式转后缀表达式

测试数据:
-12+33*(-32+9)/-3  #负数
12+(3-7*2+15)*5-(2+(5-8)*2+3)   #嵌套括号
12.6/2-1.1*5+2    #小数

解决的问题:
利用正则表达式“零宽度正后发断言”解决负数问题(“先行”不可以)
为了解决开头为负数的问题,字符串前加入空格

制作过程:
1.先实现算法
2.利用正则表达式优化输入
=end
@debug=1 # 0 1 2 看程序
@operator=Array[2]
@operator[0]=%w[+ - * /]
@operator[1]=%w[( )]
#不考虑负数
#@digit_reg=/^ \d+ (\.\d+)? $/x #x忽略空格
#@digit_reg=/(?:)?\d+(?:\.\d+)?/ #加上?: scan才正常
@digit_reg=/(?:(?<=\D)-)?\d+(?:\.\d+)?/  #解决负数问题
@ope_reg=/ \+ | \- | \* | \/ | \( | \) /x  # - 也行
@ope_method={}
@ope_method["+"]=lambda{|x,y| x+y}
@ope_method["-"]=lambda{|x,y| x-y}
@ope_method["*"]=lambda{|x,y| x*y}
@ope_method["/"]=lambda{|x,y| x/y}

def infix_to_suffix arr
    s1,s2=[],[] #stack
    arr.each do |x|
        if x =~ @digit_reg #数字处理
            s2.push format("%.2f",x).to_f
        else #非数字处理
            if @operator[0].include? x # 运算符处理
                if s1.size==0 or 
                   s1[-1]==@operator[1][0] or 
                   (@operator[0].index x) > (@operator[0].index s1[-1]) then
                    s1.push x
                else
                    s2.push s1.pop
                    redo #可用于块
                end
            elsif @operator[1].include? x #括号处理
                if x==@operator[1][0]
                    s1.push x
                else
                    s2.push s1.pop until s1.size==0 || s1[-1]==@operator[1][0]
                    if s1.size==0
                        STDERR<<"error: bracket is not match\n"
                        exit
                    else
                       s1.pop
                    end
                end
            else
                STDERR<<"error: input symbol\n"
                exit
            end
        end
    end
    while s1.size !=0
        s2.push s1.pop
    end
    s2
end
def comput_suffix arr
    s_num=[] #also a stack
    arr.each do |x|
        if x.class == Float
            s_num.push x
        elsif s_num.size>=2
            a,b=s_num.pop,s_num.pop
            r=@ope_method[x].call b,a
            puts "#{b} #{x} #{a} = #{r}" if @debug>=1
            s_num.push r
        else
            break
        end
    end
    if s_num.size!=1
        STDERR<<"error: the equ is not true\n"
        exit
    end
    format("%.2f", s_num[0] ).to_f
end
def split_num_ope str
#为了实现方便的输入
    outarr=[]
    #def不能传入local变量  *****
    define_method :handle_ope_str do |str|
        while(str=~@ope_reg)
            outarr.push $&
            str=$'
        end
    end
    while(str=~@digit_reg)
        pre,now,nxt=$`,$&,$' #匹配 前中后,保存下来否则会改变
        handle_ope_str pre.strip unless pre.nil? or pre.strip==""
        outarr.push now
        str=nxt
        puts pre+" / "+now+" / "+nxt  if @debug>=2
    end
    handle_ope_str str.strip unless str.nil? or str.strip==""
    p outarr if @debug>=1
    outarr 
end
instr=" "+gets #输入
#p instr.match @digit_reg  只匹配一个,返回metadata
#instr.scan(@digit_reg).each do |m| puts m ; end
#inarr=instr.split /\s+/ #/ #最初使用的方法
inarr=split_num_ope instr
suf=infix_to_suffix inarr
p comput_suffix suf


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值