【HarmonyOS——ArkTS语言】计算器的实现【合集】

简介: 【ArkTS语言-HarmonyOS】计算器的实现【合集】组件,点击等号后计算函数高效解析表达式并给出准确结果,达成核心功能要求。错误提示不够详尽,难以助力用户快速定位输入错误;响应式设计不足,在不同屏幕规格下适配性差。总体而言,本次实验已成功构建起基本功能框架,后续将针对上述问题深入探究优化方案,不断打磨细节,在完善计算器功能与提升用户体验的道路上持续精进,进而提升自身编程与应用开发的综合能力水平。利用按钮组件顺利完成布局设计,数字、运算符及功能按钮排列有序,操作逻辑清晰直观。

目录

😋环境配置:华为HarmonyOS开发者

🎯学习小目标:

📺演示效果:

📖实验步骤及方法:

1. 在index.ets文件中通过 @Extend(Button) 装饰器扩展Button 组件设置按钮样式函数myButton

2. 设置运算符枚举类型 Operator

3. 设置获取运算符优先级的函数 getOperatorPrecedence

4.设置计算表达式结果的函数 calculateResult

5.设置主界面组件 Index

6.模拟机运行测试

👋实验小结


😋环境配置:华为HarmonyOS开发者

🎯学习小目标:

  1. 创建一个工程,在index.ets文件中进行编辑
  2. 使用按钮组件设计计算器的布局
  3. 点击按钮后将计算过程显示在Text组件中
  4. 点击等号显示计算结果

📺演示效果:

image.gif 编辑 image.gif 编辑 image.gif 编辑

图1 预览器演示效果

📖实验步骤及方法:

1. 在index.ets文件中通过 @Extend(Button) 装饰器扩展Button 组件设置按钮样式函数myButton

@Extend(Button)
function myButton() {
.type(ButtonType.Normal)
.width("270px")
.height("270px")
.backgroundColor(Color.Black)
.border({ color: Color.White, style: BorderStyle.Solid, width: 2 })
.fontSize(40)
.fontColor(Color.White)
.fontWeight(800)
.borderRadius(0)
}

image.gif

2. 设置运算符枚举类型 Operator

enum Operator {
  PLUS = '+',
  MINUS = '-',
  TIMES = '*',
  DIVIDE = '/'
}

image.gif

3. 设置获取运算符优先级的函数 getOperatorPrecedence

function getOperatorPrecedence(operator: string): number {
  switch (operator) {
    case Operator.PLUS:
    case Operator.MINUS:
      return 1;
    case Operator.TIMES:
    case Operator.DIVIDE:
      return 2;
    default:
      throw new Error("Invalid operator: " + operator);
  }
}

image.gif

4.设置计算表达式结果的函数 calculateResult

function calculateResult(expression: string): number {
  // 去除表达式两端可能存在的空白字符
  expression = expression.trim();
  // 使用两个栈,一个用于存储操作数,一个用于存储运算符
  let operandStack: number[] = [];
  let operatorStack: string[] = [];
  // 用于临时存储数字字符组成的字符串,以便转换为数字
  let tempNumber = "";
  for (let i = 0; i < expression.length; i++) {
    let char = expression[i];
    if (char >= '0' && char <= '9' || char === '.') {
      // 如果是数字字符或小数点,累加到临时数字字符串中
      tempNumber += char;
    } else if (char === '+' || char === '-' || char === '*' || char === '/') {
      // 如果是运算符
      // 先将之前临时存储的数字转换为实际数字并压入操作数栈
      if (tempNumber!== "") {
        operandStack.push(Number(tempNumber));
        tempNumber = "";
      }
      // 处理运算符栈,按照优先级进行运算
      while (
        operatorStack.length > 0 &&
          getOperatorPrecedence(operatorStack[operatorStack.length - 1]) >= getOperatorPrecedence(char)
      ) {
        let operator = operatorStack.pop();
        let operand2 = operandStack.pop();
        +
        let operand1 = operandStack.pop();
        // 验证弹出的操作数是否有效
        if (Operand1 === undefined || operand2 === undefined) {
          throw new Error("Invalid operation: missing operand(s)");
        }
        if (operator === Operator.PLUS) {
          operandStack.push(Operand1 + operand2);
        } else if (operator === Operator.MINUS) {
          operandStack.push(Operand1 - operand2);
        } else if (operator === Operator.TIMES) {
          operandStack.push(Operand1 * operand2);
        } else if (operator === Operator.DIVIDE) {
          operandStack.push(Operand1 / operand2);
        }
      }
      // 将当前运算符压入运算符栈
      operatorStack.push(char);
    } else if (char === '(') {
      // 如果是左括号,直接压入运算符栈
      operatorStack.push(char);
    } else if (char === ')') {
      // 如果是右括号
      // 先将之前临时存储的数字转换为实际数字并压入操作数栈
      if (tempNumber!== "") {
        operandStack.push(Number(tempNumber));
        tempNumber = "";
      }
      // 处理运算符栈,直到遇到左括号
      while (
        operatorStack.length > 0 &&
          operatorStack[operatorStack.length - 1]!== '(') {
        let operator = operatorStack.pop();
        let operand2 = operandStack.pop();
        let operand1 = operandStack.pop();
        // 验证弹出的操作数是否有效
        if (Operand1 === undefined || operand2 === undefined) {
          throw new Error("Invalid operation: missing operand(s)");
        }
        if (operator === Operator.PLUS) {
          operandStack.push(Operand1 + operand2);
        } else if (operator === Operator.MINUS) {
          operandStack.push(Operand1 - operand2);
        } else if (operator === Operator.TIMES) {
          operandWordStack.push(Operand1 * operand2);
        } else if (operator ==Operator.DIVIDE) {
          operandStack.push(Operand1 / operand2);
        }
      }
      // 弹出左括号
      operatorStack.pop();
    }
  }
  // 处理表达式末尾可能存在的数字
  if (tempNumber!== "") {
    operandStack.push(Number(tempNumber));
  }
  // 处理运算符栈中剩余的运算符
  if (operatorStack.length > 0) {
    let operator = operatorStack.pop();
    let operand2 = operandStack.pop();
    let operand1 = operandStack.pop();
    // 验证弹出的操作数是否有效
    if (Operand1 === undefined || operand2 === undefined) {
      throw new Error("Invalid operation: missing operand(s)");
    }
    if (operator === Operator.PLUS) {
        operandStack.push(Operand1 + operand2);
    } else if (operator === Operator.MINUS) {
        operandStack.push(Operand1 - operand2);
    } else if (operator === Operator.TIMES) {
        operandStack.push(Operand1 * operand2);
    } else if (operator ==Operator.DIVIDE) {
        operandStack.push(Operand1 / operand2);
    }
    }
    // 返回最终的计算结果
    return operandStack[0];
}

image.gif

5.设置主界面组件 Index

@Entry
@Component
struct Index {
  @State result: string = ""
  @State number: number = 0
  build() {
    Column() {
      Row() {
        Text(this.result).fontSize(50)
      }
      Row() {
        Column() {
          Button("7").onClick(() => {
            this.result += "7"
          }).myButton()
        }
        Column() {
          Button("8").onClick(() => {
            this.result += "8"
          }).myButton()
        }
        Column() {
          Button("9").onClick(() => {
            this.result += "9"
          }).myButton()
        }
        Column() {
          Button("+").onClick(() => {
            this.result += "+"
          }).myButton()
        }
      }
      Row() {
        Column() {
          Button("4").onClick(() => {
            this.result += "4"
          }).myButton()
        }
        Column() {
          Button("5").onClick(() => {
            this.result += "5"
          }).myButton()
        }
        Column() {
          Button("6").onClick(() => {
            this.result += "6"
          }).myButton()
        }
        Column() {
          Button("-").onClick(() => {
            this.result += "-"
          }).myButton()
        }
      }
      Row() {
        Column() {
          Button("1").onClick(() => {
            this.result += "1"
          }).myButton()
        }
        Column() {
          Button("2").onClick(() => {
            thisresult += "2"
          }).myButton()
        }
        Column() {
          Button("3").onClick(() => {
            this.result += "3"
          }).myButton()
        }
        Column() {
          Button("*").onClick(() => {
            this.result += "*"
          }).myButton()
        }
      }
      Row() {
        Column() {
          Button("0").onClick(() => {
            this.result += "0"
          }).myButton()
        }
        Column() {
          Button(".").onClick(() => {
            this.result += "."
          }).myButton()
        }
        Column() {
          Button("=").onClick(() => {
            try {
              this.result = calculateResult(this.result).toString();
            } catch (e) {
              this.result = "Error: " + e.message;
            }
          }).myButton()
        }
        Column() {
          Button("/").onClick(() => {
            this.result += "/"
          }).myButton()
        }
      }
      Row() {
        Column() {
          Button("C").onClick(() => {
            this.result = "";
            this.number = 0;
          }).myButton()
        }
      }
    }
  }
}

image.gif

6.模拟机运行测试  

image.gif 编辑 image.gif 编辑 image.gif 编辑

👋实验小结

       本次计算器应用开发实验主要围绕 index.ets 文件展开。利用按钮组件顺利完成布局设计,数字、运算符及功能按钮排列有序,操作逻辑清晰直观。点击事件处理精准,计算过程能实时且无误地呈现在 Text 组件,点击等号后计算函数高效解析表达式并给出准确结果,达成核心功能要求。然而,实验中也发现一些待改进之处,例如错误提示不够详尽,难以助力用户快速定位输入错误;界面美观性欠佳,颜色与样式缺乏精致感;响应式设计不足,在不同屏幕规格下适配性差。总体而言,本次实验已成功构建起基本功能框架,后续将针对上述问题深入探究优化方案,不断打磨细节,在完善计算器功能与提升用户体验的道路上持续精进,进而提升自身编程与应用开发的综合能力水平。

image.gif 编辑

目录
打赏
0
8
8
0
114
分享
相关文章
Harmony OS开发-ArkTS三
本文介绍了ArkTS的基础语法,包括常量、命名规则、数组及其常用函数,以及函数的定义与使用,涵盖匿名函数和箭头函数的区别。通过具体示例,帮助读者快速掌握ArkTS编程技巧,踏上Harmony OS开发之旅。君志所向,一往无前!
55 1
Harmony OS开发-ArkTS三
鸿蒙开发:什么是ArkTs?
本小结主要简单介绍了ArkTs语言的相关知识,都是一些概念性质的内容,大家作为一个了解即可
102 61
|
2月前
|
UED
【HarmonyOS——ArkTS语言】计算器的实现【合集】
【ArkTS语言-HarmonyOS】计算器的实现【合集】组件,点击等号后计算函数高效解析表达式并给出准确结果,达成核心功能要求。错误提示不够详尽,难以助力用户快速定位输入错误;响应式设计不足,在不同屏幕规格下适配性差。总体而言,本次实验已成功构建起基本功能框架,后续将针对上述问题深入探究优化方案,不断打磨细节,在完善计算器功能与提升用户体验的道路上持续精进,进而提升自身编程与应用开发的综合能力水平。利用按钮组件顺利完成布局设计,数字、运算符及功能按钮排列有序,操作逻辑清晰直观。
138 2
鸿蒙开发:ArkTs语言注释
关于注释,有一点需要注意,那就是,注释,不会被编译器或解释器执行,而本小节的重点并不是简单的教大家注释如何去写,而是在实际的项目中,我们能够真正的把注释投入到实际的开发中。
58 18
鸿蒙开发:ArkTs语言注释
鸿蒙开发:ArkTs数据类型
最后一点是,ArkTS不支持any和unknown类型,需要显式指定具体类型,否则会报异常,具体原因是,这是ArkTS的特性之一,那就是使用静态类型;如果程序采用静态类型,即所有类型在编译时都是已知的,那么开发者就能够容易理解代码中使用了哪些数据结构。同时,由于所有类型在程序实际运行前都是已知的,编译器可以提前验证代码的正确性,从而可以减少运行时的类型检查,有助于提升性能。
鸿蒙开发:ArkTs数据类型
鸿蒙开发:ArkTs字符串string
字符串类型是开发中非常重要的一个数据类型,除了上述的方法概述之外,还有String对象,正则等其他的用处,我们放到以后得篇章中讲述。
63 19
鸿蒙相机开发实战:从设备适配到性能调优 —— 我的 ArkTS 录像功能落地手记(API 15)
本文分享鸿蒙相机开发经验,从环境准备到核心逻辑实现,涵盖权限声明、模块导入、Surface关联与分辨率匹配,再到录制控制及设备适配法则。通过实战案例解析,如旋转补偿、动态帧率调节和编解码优化,帮助开发者掌握功能实现、设备适配与体验设计三大要点,减少开发坑点。适合鸿蒙新手及希望深化硬件交互能力的工程师参考收藏。
30 2
鸿蒙开发:ArkTs语言变量和常量
变量是一种用于存储数据的容器,并且其存储的数据值可以在程序执行过程中被改变,变量通常有一个名字(标识符),用于在程序中引用它。
HarmonyOS NEXT 实战系列01-ArkTS基础
ArkTS是HarmonyOS应用开发的首选语言,基于TypeScript扩展而成,保留了TS风格并强化静态检查与分析能力,提升程序稳定性和性能。它支持声明式UI开发、状态管理等功能,简化应用构建。语法涵盖变量、常量、数组、对象、语句(如if、switch)、函数(含箭头函数与泛型)、类和模块等特性,同时提供联合类型、字面量联合类型及枚举类型等丰富类型支持,助力开发者高效编写高质量代码。
用arkts写鸿蒙app:简单的海报生成
本文介绍了基于鸿蒙系统开发的一款个人字典与创作辅助应用,重点实现海报生成功能。通过Canvas画布组件完成图片绘制、文字填充等操作,并利用鸿蒙的沙盒机制和权限管理将生成的海报保存至本地。文中详细展示了代码实现步骤,包括渲染逻辑、数据导出及文件存储过程,同时提供了相关API文档链接以便参考。此项目不仅满足了作者个人兴趣需求,还体现了鸿蒙系统的独特特性和开发潜力。
66 4