【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 编辑

目录
相关文章
|
开发框架 开发者 JavaScript
HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 三)
子组件中被@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。
|
开发框架 API 开发者
HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 二)
在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成自定义组件是不可或缺的能力。
|
2月前
|
JavaScript 安全 前端开发
【HarmonyOS开发】ArkTS基础语法及使用(鸿蒙开发基础教程)
【HarmonyOS开发】ArkTS基础语法及使用(鸿蒙开发基础教程)
349 4
|
17天前
|
人工智能 自然语言处理 算法
开箱即用的个人主页页面开发实战—基于HarmonyOS 5.0 (Next)和ArkTS的实现【HarmonyOS 5.0(Next)】
本文介绍了基于HarmonyOS 5.0(Next)和ArkTS开发的开箱即用个人主页页面。HarmonyOS 5.0(Next)采用全新“和谐美学”设计理念,通过光元素模拟、多设备无缝流转及小艺助手升级,提升用户体验。文章详细解析了使用ArkTS构建个人主页页面的代码,展示了清晰的布局层次、简洁的事件处理、状态管理和组件化开发等最佳实践。这段代码不仅实现了美观的界面设计,还提供了高效的应用导航和数据传递功能,体现了对用户体验的高度关注。
118 12
开箱即用的个人主页页面开发实战—基于HarmonyOS 5.0 (Next)和ArkTS的实现【HarmonyOS 5.0(Next)】
|
17天前
|
自然语言处理 搜索推荐 数据安全/隐私保护
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
鸿蒙登录页面设计展示了 HarmonyOS 5.0(Next)的未来美学理念,结合科技与艺术,为用户带来视觉盛宴。该页面使用 ArkTS 开发,支持个性化定制和无缝智能设备连接。代码解析涵盖了声明式 UI、状态管理、事件处理及路由导航等关键概念,帮助开发者快速上手 HarmonyOS 应用开发。通过这段代码,开发者可以了解如何构建交互式界面并实现跨设备协同工作,推动智能生态的发展。
127 10
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 四)
被@Observed装饰的类,可以被观察到属性的变化;子组件中@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类的实例,和父组件中对应的状态变量建立双向数据绑定。这个实例可以是数组中的被@Observed装饰的项,或者是class object中是属性,这个属性同样也需要被@Observed装饰。单独使用@Observed是没有任何作用的,需要搭配@ObjectLink或者@Prop使用。
|
8月前
|
JavaScript API 开发者
【HarmonyOS 4.0 应用开发实战】ArkTS 快速入门
【HarmonyOS 4.0 应用开发实战】ArkTS 快速入门
820 0
|
8月前
|
JavaScript 前端开发 索引
【HarmonyOS 4.0 应用开发实战】TypeScript入门之接口详讲
【HarmonyOS 4.0 应用开发实战】TypeScript入门之接口详讲
105 0
|
8月前
|
存储 Java 数据管理
HarmonyOS实战—HarmonyOS入门第一课
HarmonyOS实战—HarmonyOS入门第一课
130 0
HarmonyOS实战—HarmonyOS入门第一课
|
8月前
|
IDE 开发工具 Swift
Swift语言的教程
Swift语言的教程
125 1

热门文章

最新文章

下一篇
开通oss服务