HarmonyOS应用开发——实现简单计算器

先看看如何使用栈进行表达式求值

若还有点困惑,那看看视频讲解吧

3.3.2_栈在表达式求值中的应用_哔哩哔哩_bilibili

计算器页面:


实现代码:

//定义处理输入数据及计算数值的函数
function  ParseAndCalculate(expression:string):number {
  if(expression.length===0) return 0;              //若表达式长度为0,直接返回

  let operators: string[] = [];                   //存放运算符
  let num:number[]=[]                             //存放数值
 

     //进行计算的函数
  const applyOperator = (a: number, b: number, op: string): number => { 
    switch (op) {
      case '+':
        return a + b;
      case '-':
        return a - b;
      case '*':
        return a * b;
      case '/':
        if(b===0)
        {
          
          console.error('输入非法')              //若除数为0,则打印错误日志,不返回结果
        }
        return a / b;
      case '%':
        return a % b
      default: {
        console.log(op)
        return 0
      }

    }
  }
    //定义处理表达式的函数
const parse=(exp:string)=>{
    let res:string=''                          //设置一个空串来存取数字
    let i=0                                    //记录已处理字符的个数
    let is_number:boolean=false;               //判断是否为数字部分,若不是则将res转化为数字
  for(let char of exp)                          //用for of 循环遍历字符串
  {
      i++;    
      if(char==='(')                      //若为"(",则直接放入operations[],直接进入下一循环
      {
        operators.push('(')
        continue;
      }

      if(char==='.'&&res.length===0) res+=0           //处理输入为‘.9'类似情况,此时res为空
      else if(char==='-'&&res.length===0&&operators[operators.length-1]!==')') 
                  {res+=char;continue}                             // 处理负数  
      else if(char==='+'&&num.length===0&&res.length===0) {res+=0}
                                                     //处理表达式第一位为‘+’情况
      if((char>='0'&&char<='9')||char==='.')         //判断是否为数字部分
      {

        res+=char;
        if(i===exp.length)                     //若为最后一个字符,则需将res转换为数值
        {num.push(parseFloat(res))
          res=''
        }
        is_number=true
        continue;
      }
       else if(is_number){                 //若上一次处理的字符为数字,但此次不是,则进行转换
        num.push(parseFloat(res))
        res=''
        is_number=false
      }
      if(char===')')                       //若为‘)’则开始计算括号内表达式的结果
     {
      let ope:string=operators.pop() as string
       while(ope!=='(')
       {
        let y:number=num.pop() as number
        let x:number=num.pop() as number
        num.push(applyOperator(x,y,ope))             
                                          //将计算结果存入操作数数组,成为下一次运算的操作数
        ope=operators.pop() as string
       }
       continue
     }


    if(char==='- '||char==='+'||char==='*'||char==='/'||char==='%'||char==='('||char===')')
     {
        if(operators.length===0) operators.push(char)          //此时为第一个运算符直接入组
        else if(char==='*'||char==='/'||char==='%')         //根据运算符优先级进行处理
       {
          if(operators[(operators.length)-1]==='+'||operators[operators.length-1]==='- 
                  '||operators[operators.length-1]==='(')
           {
            operators.push(char)
           }
          else if(operators[operators.length-1]==='*'||operators[operators.length- 1]==='/'||operators[operators.length-1]==='%')
           {
            let ope:string=operators.pop() as string
            let y:number=num.pop() as number
            let x:number=num.pop() as number
            num.push(applyOperator(x,y,ope))
            operators.push(char)
           }

       }
        else if(char==='+'||char==='-')
        {
          if(operators[operators.length-1]!=='(')
          {
            let ope:string=operators.pop() as string
            let y:number=num.pop() as number
            let x:number=num.pop()  as number
            num.push(applyOperator(x,y,ope))
            if(operators[operators.length-1]==='-')
            {
              let ope:string=operators.pop() as string
              let y:number=num.pop() as number
              let x:number=num.pop()  as number
              num.push(applyOperator(x,y,ope))
            }
            operators.push(char)
          }
          else{
            operators.push(char)
           }
        }
     }

   }
    //处理剩余数据
     while (operators.length) {
        let x:number=0
         let y:number=0
        let ope: string = operators.pop() as string
       if(ope==='(') continue
         if(num.length===1)
          {  y=0
            x=num.pop() as number
          }
         else{
         y= num.pop() as number
         x = num.pop() as number
          }
        console.log(`${x},${y},${ope}`)
        num.push(applyOperator(x, y, ope))
     }
   }

  //调用表达式处理函数
   parse(expression);                             
   if(num[0])             //处理最后操作数数组第一个元素即为计算结果
    return num[0]
   return  0
 }
 
@Extend(Row) function B_row(){                              
  .width('100%')
  .justifyContent(FlexAlign.SpaceEvenly)
}

//定义创建按钮的组件
@Component                   
struct createButton{
  value:number|string=''
  f_size:number=40
    build() {
    Button(`${this.value}`)
      .fontSize(this.f_size)
      .width(75)
      .height(70)
      .borderRadius(10)
      .backgroundColor("#ff88cd4b")

  }
}

class ButtonValue{
  value:Array<number|string>=[]
  constructor(array:Array<string|number>) {
    this.value=array
  }
}
                               //ButtonValue类的数组
const B_V=[
  new ButtonValue([7,8,9]),
  new ButtonValue([4,5,6]),
  new ButtonValue([1,2,3]),
  new ButtonValue(['%',0,'.']),
  new ButtonValue(['*','/','+']),
]

 //程序入口

@Entry
@Component
struct CaculatorPage {
  @State F_size:number=20
  @State message_s:string=''                 //保存计算表达式
  @State message_r:string=''                 //保存计算结果
  @State input:boolean=true                  //用于判断是否为输入状态
  @State radius:number=20
  height_T:number=150                        //文本框高度
  build() {
    Column({space:8}){
      Row(){
         //显示数值及结果区
        Column() {
          Text(this.message_s)
            .textOverflow({overflow:TextOverflow.MARQUEE})
            .width('100%')
            .height(this.height_T)
            .fontSize(50)
            .backgroundColor('#ff79efca')
            .shadow({radius:20,color:'#ff04dd91'})
   .borderRadius({topLeft:20,topRight:20,bottomLeft:this.radius,bottomRight:this.radius})
            .textAlign(TextAlign.End)
            .linearGradient({ angle: 45, colors: [['#ff79efca', 0.5], ['#ff93eacf', 0.5],] })
          if(!this.input)                    //输入结束,则显示计算结果
          {
            Text(this.message_r)
              .width('100%')
              .textOverflow({ overflow:TextOverflow.MARQUEE})
              .height(70)
              .fontSize(50)
              .backgroundColor('#ff79efca')
              .borderRadius({bottomLeft:20,bottomRight:20})
              .textAlign(TextAlign.End)
              .linearGradient({ angle: 45, colors: [['#ff79efca', 0.8], ['#ff93eacf', 0.8],] })
              .animation({duration:100})
              .transition({type:TransitionType.All})
          }

        }
      }
      .width('100%')
      .padding(20)
      .backgroundColor('#ccc')
      .borderRadius(5)

      //键盘部分
      Column({space:10}) {
      
        ForEach(B_V,(item:ButtonValue,id)=>{      
                                         //采用双层ForEach循环渲染按钮,也可采用Grid网格布局
          Row() {
            ForEach(item.value, (val: number) => {

              createButton({ value: val }).onClick(() => {
                this.message_s += val
                console.log(`${id}`)
              })

            })
            if(id===0)                                    // 此时为第一行,渲染‘重置’按钮
            {
              createButton({ value: '重置' ,f_size:this.F_size}).onClick(this.onResetClick.bind(this))
            }
            if(id===1)
            {
              createButton({ value: '删除' ,f_size:this.F_size}).onClick(this.onDeleteClick.bind(this))
            }
            if(id===2)
            {
              Button(`(`)
                .fontSize(28)
                .width(40)
                .height(70)
                .borderRadius(10)
                .backgroundColor("#ff88cd4b")
                .onClick(()=>{
                this.message_s+='('
              })
              Button(`)`)
                .fontSize(28)
                .width(40)
                .height(70)
                .borderRadius(10)
                .backgroundColor("#ff88cd4b")
                .onClick(()=>{
                this.message_s+=')'
              })
            }
            if(id===3)
            {
              createButton({value:'='}).onClick(()=>{
                this.height_T=80
                this.radius=0
                let a=calculate(this.message_s)
                this.message_r=a.toString()
                this.input=false
              })
            }
            if(id===4)
            {
              createButton({value:'-'}).onClick(()=>{
                if(this.message_r)
                {
                  this.message_s=this.message_r
                }
                this.message_s+='-'
              })
            }

        })
     
      }
      .width('100%')
      .padding(10)
      .layoutWeight(1)
      .borderRadius(20)
      .backgroundColor('#ffdddada')
      .justifyContent(FlexAlign.SpaceEvenly)

    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.SpaceEvenly)
    .padding(5)
  }

           
  onDeleteClick(){                                           //点击'删除'按钮时的事件                             
    if(this.message_s.length>0) {
      this.input=true
      this.height_T=150
      this.radius=20
      this.message_s = this.message_s.substring(0,this.message_s.length - 1)

    }
  }
  onResetClick(){                                           //点击'重置'按钮时的事件
    if(this.message_s.length>0)
    {
      this.input=true
      this.height_T=150
      this.radius=20
      this.message_s=this.message_s.substring(0,0)
      this.message_r=''}
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值