ToB企服应用市场:ToB评测及商务社交产业平台
标题:
使用ArkTs举行计算器的实现
[打印本页]
作者:
用户云卷云舒
时间:
2024-10-23 14:38
标题:
使用ArkTs举行计算器的实现
1、写出大抵的计算器构造
在calcultorDemo.ets文件中
import {calculatorResult} from './calculatorResult'
import numberstack from './NumberStack'
import characterstack from './CharacterStack'
@Entry
@Component
struct 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)的编写
@Component
export 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'}
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4