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