当前位置:首页 » 《关注互联网》 » 正文

使用ArkTs进行计算器的实现

7 人参与  2024年09月14日 18:41  分类 : 《关注互联网》  评论

点击全文阅读


使用ArkTs进行计算器的实现,基于deveco-studio3.1.1,新版未尝试

1、写出大致的计算器构造在calcultorDemo.ets文件中在calculatorResult.ets中 2、进行计算机的功能部分给每个按钮分别添加点击事件完成value的计算事件,利用栈进行算术表达式的求值: 3、完整代码(一个文件)

1、写出大致的计算器构造

在calcultorDemo.ets文件中

import {calculatorResult} from './calculatorResult'import numberstack  from './NumberStack'import characterstack from './CharacterStack'@Entry@Componentstruct calcultorDemo {  @State value:string =''   @State result:string=''  @State opacityValue:number=0  @State fontSizeValue:number=30  numbers :string[]=['(',')','÷','×','1','2','3','-','4','5','6','+','7','8','9']  numbers2:string[]=['%','0','.']  build() {    Column(){      calculatorResult({value:$value,result:this.result,opacityValue:$opacityValue,fontSizeValue:$fontSizeValue})      Column(){//计算机主体页面        Grid(){          GridItem(){            Text('MC')              .TextStyle()          }          .oneStyle()//MC(清零)工具          GridItem(){            Text('MR')              .TextStyle()          }          .oneStyle()          GridItem(){            Image($r('app.media.delete'))              .fillColor(Color.Blue)              .height(40)          }          .oneStyle()          .onClick(()=>{            this.value=this.value.slice(0,this.value.length-1)            this.result=''          })          GridItem(){            Text('C')              .TextStyle()          }          .oneStyle()          .onClick(()=>{            this.value=''            this.result=''          })          ForEach(this.numbers,item=>{            GridItem(){              Text(item)                .TextStyle()            }            .onClick(()=>{              if (this.value === '' && (item === '+' || item === '-' || item === '×' || item === '÷' || item === '%')) {                return              }//判断点击的第一个字符是不是运算符,若是则返回              if (this.value[this.value.length - 1] === '+' || this.value[this.value.length - 1] === '-' ||              this.value[this.value.length - 1] === '×' || this.value[this.value.length - 1] === '÷' ||              this.value[this.value.length - 1] === '%') {                // 如果当前点击的是运算符,则替换最后一个运算符                if (item === '+' || item === '-' || item === '×' || item === '÷' || item === '%') {                  this.value = this.value.slice(0, this.value.length - 1) + item                } else {                  this.value += item                }              } else {                this.value = this.value.concat(item)              }            })            .oneStyle()          })          GridItem(){            Text('=')              .TextStyle()              .fontColor(Color.White)          }          .rowStart(5)          .rowEnd(6)          .borderRadius(40)          .backgroundColor(Color.Blue)          .onClick(()=>{            this.result=total(checkParentheses(this.value+'#').cleanedExpression)            this.opacityValue=1            this.fontSizeValue=50          })          ForEach(this.numbers2,item=>{            GridItem(){              Text(item)                .TextStyle()            }            .onClick(()=>{this.value=this.value.concat(item)})            .oneStyle()          })        }        .width('100%')        .height(500)        .columnsTemplate('1fr 1fr 1fr 1fr')        .rowsTemplate('1fr 1fr 1fr 1fr 1fr 1fr')        .columnsGap(8)        .rowsGap(12)        .padding(12)        .backgroundColor('#fff6f0f0')        .borderRadius({topLeft:20,topRight:20})      }      .layoutWeight(1)      .justifyContent(FlexAlign.End)    }    .height('100%')  }}@Styles function oneStyle(){  .backgroundColor(Color.White)  .height(70)  .width(70)  .borderRadius(40)  .shadow({color:Color.Gray,radius:5})}@Extend(Text) function TextStyle() {  .fontSize(25)  .fontWeight(400)}

以上代码写出计算机的键盘部分,使用Grid组件进行键盘的分隔,以及对相同功能的按钮进行ForEach循环渲染减少占有空间
在这里插入图片描述

在calculatorResult.ets中

进行键盘输入(TextInput)和输出(Text)的编写

@Componentexport struct  calculatorResult{  @Link value:string  @Prop result:string  @Link opacityValue:number  @Link fontSizeValue:number  build() {      Column(){        TextInput({text:this.value})          .height(80)          .margin({top:60})          .placeholderFont({size:60})          .fontSize(60)          .fontWeight(450)          .textAlign(TextAlign.End)          .backgroundColor(Color.White)        Text(this.result)          .opacity(this.opacityValue)          .width('100%')          .height(60)          .fontSize(this.fontSizeValue)          .fontWeight(450)          .textAlign(TextAlign.End)          .animation({duration:500})            // @ts-ignore          .textOverflow(TextOverflow.Clip)      }  }}

经过以上两个文件的渲染后,计算机的大概形状显示出来,如图所示:
在这里插入图片描述

2、进行计算机的功能部分

给每个按钮分别添加点击事件

1、对1,2,3,4,5,6,7,8,9,+, - , × ,÷添加存储表达式的点击事件,定义 @State value:string =‘’ 在每次进行点击时,对所点击的内容做出判断,储存所点击的内容。

.onClick(()=>{              if (this.value === '' && (item === '+' || item === '-' || item === '×' || item === '÷' || item === '%')) {                return              }//判断点击的第一个字符是不是运算符,若是则返回              if (this.value[this.value.length - 1] === '+' || this.value[this.value.length - 1] === '-' ||              this.value[this.value.length - 1] === '×' || this.value[this.value.length - 1] === '÷' ||              this.value[this.value.length - 1] === '%') {                // 如果在上一个字符是运算符时,当前点击的是运算符,则替换最后一个运算符                if (item === '+' || item === '-' || item === '×' || item === '÷' || item === '%') {                  this.value = this.value.slice(0, this.value.length - 1) + item                } else {                //若当前点击不是运算符而是数字时,则继续输入表达式                  this.value += item                }              } else {                this.value = this.value.concat(item)              }            })

2、对删除按钮:定义 @State result:string=''进行计算机结果的保存,方便后续渲染在Text组件中。

.onClick(()=>{            this.value=this.value.slice(0,this.value.length-1)            this.result=''          })

3、对于清零工具则将value和result都置为空

.onClick(()=>{            this.value=''            this.result=''          })

完成value的计算事件,利用栈进行算术表达式的求值:

主要思路:
1、将中缀表达式转为后缀表达式;
2、对后缀表达式求值;
具体可参考:栈的应用-表达式求值

代码如下:
1、在calcultorDemo.ets中:

//检查括号是否多余,且若前括号多余则去掉多余的前括号function checkParentheses(expression: string): { valid: boolean, cleanedExpression: string } {  let stack = []  let cleanedExpression = expression//判断表达式括号是否对应  for (let ch of expression) {    if (ch === '(') {      stack.push(ch)    } else if (ch === ')') {//后括号多余则直接返回错误      if (stack.length === 0) {        return { valid: false, cleanedExpression: expression }      }      stack.pop()    }  }  //若不对应,去掉多余的前括号  while (stack.length > 0) {    let index = cleanedExpression.indexOf('(')    if (index !== -1) {      cleanedExpression = cleanedExpression.slice(0, index) + cleanedExpression.slice(index + 1)    }    stack.pop()  }  console.log(cleanedExpression)  return { valid: stack.length === 0, cleanedExpression }}//对表达式求值function total(expression:string){  characterstack.push('#')  let i=0  let ch=expression[i]  while (ch!='#'||characterstack.peek()!='#') {    if(!Instring(ch)){//进行多位数的入栈      let numStr = ch      while (i + 1 < expression.length && !Instring(expression[i + 1])) {        ch = expression[++i]        numStr += ch      }      numberstack.push(numStr)      ch = expression[++i]    }    else{      switch (Precede(characterstack.peek(),ch)){        case '<':{          characterstack.push(ch);          ch=expression[++i]          break        }        case '>':{          let theta= characterstack.pop()          let b=numberstack.pop()          let a=numberstack.pop()          numberstack.push(Operate(a,theta,b))          break        }        case '=':{          characterstack.pop()          ch=expression[++i]          break        }      }    }  }  return numberstack.peek()}//判断ch是否为运算符function Instring(ch:string){  let num:string[]=['+','-','(',')','÷','×','#','%']  return num.includes(ch)}//判断运算符的优先级function Precede(thetal:string,thetal2:string):string{  if((thetal=='('&&thetal2==')')||(thetal=='#'&&thetal2=='#')){    return '='  }  else if(thetal=='('||thetal=='#'||thetal2=='('||(thetal=='+'||thetal=='-')&&(thetal2=='×'||thetal2=='÷'||thetal2=='%')){    return '<'  }  else return '>'}//计算两数的运算结果function Operate(first:string,theta:string,second:string):string{  switch (theta){    case '+':      return ((+first)+(+second)).toString()    case '-':      return ((+first)-(+second)).toString()    case '×':      return ((+first)*(+second)).toString()    case '÷':      return ((+first)/(+second)).toString()    case '%':      return ((+first)%(+second)).toString()  }  return 'NaN'}

2、在CharacterStack.ets中进行字符栈的初始化,并进行导出;

//运算符栈 class CharacterStack{  private characters:string[]  constructor() {    this.characters=[]  }  //入栈  push(item:string){    this.characters.push(item)  }  //出栈  pop(){    return this.characters.pop()  }  //返回栈顶元素  peek(){    return this.characters[this.characters.length-1]  }  //判断栈是否为空  isEmpty(){    return this.characters.length===0  }  //清空栈内元素  clear(){    this.characters=[]  }  //获取栈内元素数量  size():number{    return this.characters.length  }}const characterstack =new CharacterStack()export default  characterstack

3、在NumberStack.ets中进行数字栈的初始化,并进行导出;

//数字栈export class NumberStack{  private numbers:string[]  constructor() {    this.numbers=[]  }  //入栈  push(item:string){    this.numbers.push(item)  }  //出栈  pop(){    return this.numbers.pop()  }  //返回栈顶元素  peek(){    return this.numbers[this.numbers.length-1]  }  //判断栈是否为空  isEmpty(){    return this.numbers.length===0  }  //清空栈内元素  clear(){    this.numbers=[]  }  //获取栈内元素数量  size():number{    return this.numbers.length  }}const numberstack =new NumberStack()export default  numberstack

已解决问题:
1、括号不对应,对前括号去掉,或直接报错;
2、重复输入符号的问题;
3、首相为符号的问题;

存在问题:
1、“3-”不可以输出正常的3;
在这里插入图片描述
2、对负数不可进行计算;…(存在未发现问题)

3、完整代码(一个文件)

@Entry@Componentstruct calcultorDemo {  @State value:string =''  @State result:string=''  @State opacityValue:number=0  @State fontSizeValue:number=30  numbers :string[]=['(',')','÷','×','1','2','3','-','4','5','6','+','7','8','9']  numbers2:string[]=['%','0','.']  build() {    Column(){      Column(){        TextInput({text:this.value})          .height(80)          .margin({top:60})          .placeholderFont({size:60})          .fontSize(60)          .fontWeight(450)          .textAlign(TextAlign.End)          .backgroundColor(Color.White)        Text(this.result)          .opacity(this.opacityValue)          .width('100%')          .height(60)          .fontSize(this.fontSizeValue)          .fontWeight(450)          .textAlign(TextAlign.End)          .animation({duration:500})            // @ts-ignore          .textOverflow(TextOverflow.Clip)      }      Column(){//计算机主体页面        Grid(){          GridItem(){            Text('MC')              .TextStyle()          }          .oneStyle()//MC(清零)工具          GridItem(){            Text('MR')              .TextStyle()          }          .oneStyle()          GridItem(){            Image($r('app.media.delete'))              .fillColor(Color.Blue)              .height(40)          }          .oneStyle()          .onClick(()=>{            this.value=this.value.slice(0,this.value.length-1)            this.result=''          })          GridItem(){            Text('C')              .TextStyle()          }          .oneStyle()          .onClick(()=>{            this.value=''            this.result=''          })          ForEach(this.numbers,item=>{            GridItem(){              Text(item)                .TextStyle()            }            .onClick(()=>{              if (this.value === '' && (item === '+' || item === '-' || item === '×' || item === '÷' || item === '%')) {                return              }//判断点击的第一个字符是不是运算符,若是则返回              if (this.value[this.value.length - 1] === '+' || this.value[this.value.length - 1] === '-' ||              this.value[this.value.length - 1] === '×' || this.value[this.value.length - 1] === '÷' ||              this.value[this.value.length - 1] === '%') {                // 如果当前点击的是运算符,则替换最后一个运算符                if (item === '+' || item === '-' || item === '×' || item === '÷' || item === '%') {                  this.value = this.value.slice(0, this.value.length - 1) + item                } else {                  this.value += item                }              } else {                this.value = this.value.concat(item)              }            })            .oneStyle()          })          GridItem(){            Text('=')              .TextStyle()              .fontColor(Color.White)          }          .rowStart(5)          .rowEnd(6)          .borderRadius(40)          .backgroundColor(Color.Blue)          .onClick(()=>{            this.result=total(checkParentheses(this.value+'#').cleanedExpression)            this.opacityValue=1            this.fontSizeValue=50          })          ForEach(this.numbers2,item=>{            GridItem(){              Text(item)                .TextStyle()            }            .onClick(()=>{this.value=this.value.concat(item)})            .oneStyle()          })        }        .width('100%')        .height(500)        .columnsTemplate('1fr 1fr 1fr 1fr')        .rowsTemplate('1fr 1fr 1fr 1fr 1fr 1fr')        .columnsGap(8)        .rowsGap(12)        .padding(12)        .backgroundColor('#fff6f0f0')        .borderRadius({topLeft:20,topRight:20})      }      .layoutWeight(1)      .justifyContent(FlexAlign.End)    }    .height('100%')  }}@Styles function oneStyle(){  .backgroundColor(Color.White)  .height(70)  .width(70)  .borderRadius(40)  .shadow({color:Color.Gray,radius:5})}@Extend(Text) function TextStyle() {  .fontSize(25)  .fontWeight(400)}//运算符栈class CharacterStack{  private characters:string[]  constructor() {    this.characters=[]  }  //入栈  push(item:string){    this.characters.push(item)  }  //出栈  pop(){    return this.characters.pop()  }  //返回栈顶元素  peek(){    return this.characters[this.characters.length-1]  }  //判断栈是否为空  isEmpty(){    return this.characters.length===0  }  //清空栈内元素  clear(){    this.characters=[]  }  //获取栈内元素数量  size():number{    return this.characters.length  }}const characterstack =new CharacterStack()//数字栈export class NumberStack{  private numbers:string[]  constructor() {    this.numbers=[]  }  //入栈  push(item:string){    this.numbers.push(item)  }  //出栈  pop(){    return this.numbers.pop()  }  //返回栈顶元素  peek(){    return this.numbers[this.numbers.length-1]  }  //判断栈是否为空  isEmpty(){    return this.numbers.length===0  }  //清空栈内元素  clear(){    this.numbers=[]  }  //获取栈内元素数量  size():number{    return this.numbers.length  }}const numberstack =new NumberStack()//检查括号是否多余,且若前括号多余则去掉多余的前括号function checkParentheses(expression: string): { valid: boolean, cleanedExpression: string } {  let stack = []  let cleanedExpression = expression  for (let ch of expression) {    if (ch === '(') {      stack.push(ch)    } else if (ch === ')') {      if (stack.length === 0) {        return { valid: false, cleanedExpression: expression }      }      stack.pop()    }  }  // 去掉多余的前括号  while (stack.length > 0) {    let index = cleanedExpression.indexOf('(')    if (index !== -1) {      cleanedExpression = cleanedExpression.slice(0, index) + cleanedExpression.slice(index + 1)    }    stack.pop()  }  console.log(cleanedExpression)  return { valid: stack.length === 0, cleanedExpression }}function total(expression:string){  characterstack.push('#')  let i=0  let ch=expression[i]  while (ch!='#'||characterstack.peek()!='#') {    if(!Instring(ch)){//进行多位数的入栈      let numStr = ch      while (i + 1 < expression.length && !Instring(expression[i + 1])) {        ch = expression[++i]        numStr += ch      }      numberstack.push(numStr)      ch = expression[++i]    }    else{      switch (Precede(characterstack.peek(),ch)){        case '<':{          characterstack.push(ch);          ch=expression[++i]          break        }        case '>':{          let theta= characterstack.pop()          let b=numberstack.pop()          let a=numberstack.pop()          numberstack.push(Operate(a,theta,b))          break        }        case '=':{          characterstack.pop()          ch=expression[++i]          break        }      }    }  }  return numberstack.peek()}//判断ch是否为运算符function Instring(ch:string){  let num:string[]=['+','-','(',')','÷','×','#','%']  return num.includes(ch)}//判断运算符的优先级function Precede(thetal:string,thetal2:string):string{  if((thetal=='('&&thetal2==')')||(thetal=='#'&&thetal2=='#')){    return '='  }  else if(thetal=='('||thetal=='#'||thetal2=='('||(thetal=='+'||thetal=='-')&&(thetal2=='×'||thetal2=='÷'||thetal2=='%')){    return '<'  }  else return '>'}//计算两数的运算结果function Operate(first:string,theta:string,second:string):string{  switch (theta){    case '+':      return ((+first)+(+second)).toString()    case '-':      return ((+first)-(+second)).toString()    case '×':      return ((+first)*(+second)).toString()    case '÷':      return ((+first)/(+second)).toString()    case '%':      return ((+first)%(+second)).toString()  }  return 'NaN'}

点击全文阅读


本文链接:http://zhangshiyu.com/post/160007.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1