Linux下Bash脚本简易计算器多问题排查与修正求助
Bash简易计算器问题排查与修复
问题概述
- 初始版本无法询问算术操作的第二个操作数,且不支持负数作为操作数;
- Update 1版本仍存在输出逻辑错误;
- Update 2版本中非算术操作(如MS、C、MR等)的流程与显示异常。
初始版本脚本
#!/bin/bash # Display user instructions echo "Welcome to the Simple Calculator" echo "Instructions:" echo "Enter operand: Any digit, MR, MC, Clear (C), Off (X)" echo "Enter operator: +, -, *, /, MS, M+, MC, Clear (C), Off (X)" echo "------------------------------------------" # Initialize variables result=0 memory=0 while true; do # Start an infinite loop to keep the calculator running # Prompt for operand read -p "Enter operand: " input_operand # Use 'read' to get user input for operand and store it in 'input_operand' case "$input_operand" in [0-9]*) operand="$input_operand";;; # If input_operand is a digit, assign it to the 'operand' variable "MR") operand="$result";;; # If input_operand is "MR", use the previous result as the operand "MC") memory=0; echo "0 -> M"; continue;;; # If input_operand is "MC", clear the memory and display the message "C") result=0; echo "results cleared"; continue;;; # If input_operand is "C", clear the result and display the message "X") echo "Good bye."; exit 0;;; # If input_operand is "X", exit the script with a farewell message *) echo "Invalid input. Please re-enter operand."; continue;;; # For any other input, display an error message and continue to the next iteration esac # Prompt for operator read -p "Enter operator: " operator # Use 'read' to get user input for the operator and store it in 'operator' case "$operator" in "+") result=$((result + operand));;; # If the operator is "+", perform addition "-") result=$((result - operand));;; # If the operator is "-", perform subtraction "*") result=$((result * operand));;; # If the operator is "*", perform multiplication "/") if [ "$operand" -eq 0 ]; then echo "Can't divide by zero. Please re-enter divisor." continue else result=$((result / operand)) fi # If the operator is "/", handle division with a check for division by zero ;; "MS") memory="$result"; echo "$result -> M";;; # If the operator is "MS", store the result in memory and display a message "M+") memory=$((memory + result));;; # If the operator is "M+", add the result to the memory "MR") operand="$memory";;; # If the operator is "MR", use the value from memory as the operand "MC") memory=0; echo "0 -> M";;; # If the operator is "MC", clear the memory and display a message "C") result=0; echo "results cleared";;; # If the operator is "C", clear the result and display a message "X") echo "Good bye."; exit 0;;; # If the operator is "X", exit the script with a farewell message *) echo "Invalid operator. Please re-enter operator."; continue;;; # For any other input, display an error message and continue to the next iteration esac echo "$result $operator $operand = $result" # Display the result of the current operation done
初始版本错误输出
Welcome to the Simple Calculator Instructions: Enter operand: Any digit, MR, MC, Clear (C), Off (X) Enter operator: +, -, *, /, MS, M+, MC, Clear (C), Off (X) ------------------------------------------ Enter operand: 3 Enter operator: * 0 * 3 = 0 Enter operand: 4 Enter operator: + 4 + 4 = 4 Enter operand:
Update 1修改后脚本
#!/bin/bash # Display user instructions echo "Welcome to the Simple Calculator" echo "Instructions:" echo "Enter operand: Any digit, MR, MC, Clear (C), Off (X)" echo "Enter operator: +, -, *, /, MS, M+, MC, Clear (C), Off (X)" echo "------------------------------------------" # Initialize variables result=0 memory=0 # Function to get an operand get_operand() { read -p "Enter operand: " input_operand case "$input_operand" in [0-9]*) operand="$input_operand";;; "MR") operand="$result";;; "MC") memory=0; echo "0 -> M";;; "C") result=0; echo "results cleared";;; "X") echo "Good bye."; exit 0;;; *) echo "Invalid input. Please re-enter operand." get_operand;; esac } # Function to get an operator get_operator() { read -p "Enter operator: " operator case "$operator" in "+"|"-"|"*"|"/") ;; "MS") memory="$result"; echo "$result -> M";;; "M+") memory=$((memory + result));;; "MR") operand="$memory";;; "MC") memory=0; echo "0 -> M";;; "C") result=0; echo "results cleared";;; "X") echo "Good bye."; exit 0;;; *) echo "Invalid operator. Please re-enter operator." get_operator;; esac } # Initial operand entry get_operand while true; do get_operator if [ "$operator" == "MS" ] || [ "$operator" == "M+" ]; then continue fi get_operand case "$operator" in "+") result=$((result + operand));;; "-") result=$((result - operand));;; "*") result=$((result * operand));;; "/") if [ "$operand" -eq 0 ]; then echo "Can't divide by zero. Please re-enter divisor." get_operand else result=$((result / operand)) fi ;; esac echo "$result $operator $operand = $result" done
Update 1错误输出
Welcome to the Simple Calculator Instructions: Enter operand: Any digit, MR, MC, Clear (C), Off (X) Enter operator: +, -, *, /, MS, M+, MC, Clear (C), Off (X) ------------------------------------------ Enter operand: 3 Enter operator: + Enter operand: 4 4 + 4 = 4 Enter operator:
Update 2修改后脚本
#!/usr/bin/env bash # Initialize variables result=0 memory=0 # Function to get an operand get_operand() { local input while true; do read -p "Enter operand: " input case "$input" in [0-9]*) echo "$input"; break;;; "MR") echo "$result"; break;;; "MC") memory=0; echo "0 -> M";;; "C") result=0; echo "results cleared";;; "X") echo "Good bye."; exit 0;;; *) echo "Invalid input. Please re-enter operand." esac done } # Function to get an operator get_operator() { local input while true; do read -p "Enter operator: " input case "$input" in "+"|"-"|"*"|"/") echo "$input"; break;;; "MS") memory="$result"; echo "$result -> M";;; "M+") memory=$((memory + result));;; "MR") echo "$memory"; break;;; "MC") memory=0; echo "0 -> M";;; "C") result=0; echo "results cleared";;; "X") echo "Good bye."; exit 0;;; *) echo "Invalid operator. Please re-enter operator." esac done } # Initial operand entry result=$(get_operand) while true; do operator=$(get_operator) operand=$(get_operand) prev_result="$result" case "$operator" in "+") result=$((result + operand));;; "-") result=$((result - operand));;; "*") result=$((result * operand));;; "/") if [ "$operand" -eq 0 ]; then echo "Can't divide by zero. Please re-enter divisor." continue fi result=$((result / operand)) ;; esac echo "$prev_result $operator $operand = $result" done
Update 2错误输出
Enter operand: 3 Enter operator: + Enter operand: 4 3 + 4 = 7 Enter operator: - Enter operand: 12 7 - 12 = -5 Enter operator: MS Enter operator: * Enter operand: 3 -5 -5 -> M * 3 = -5 Enter operator: C Enter operator: C Enter operator: MR Enter operand:
预期正确输出示例
$ ./calc [ *** User instructions displayed *** ] Enter operand: 3 Enter operator: + Enter operand: 4 3 + 4 = 7 Enter operator: - Enter operand: 12 7 - 12 = -5 Enter operator: MS -5 -> M Enter operator: * Enter operand: 3 -5 * 3 = -15 Enter operator: C results cleared Enter operand: MR M -> -5 Enter operator: * Enter operand: MR M -> -5 -5 * -5 = 25 Enter operator: M+ 25 + -5 = 20 -> M Enter operator: / Enter operand: 0 Can't divide by zero. Please re-enter divisor. Enter operand: 0 Can't divide by zero. Please re-enter divisor. Enter operand: -6 25 / -6 = -4 Enter operator: + Enter operand: C results cleared Enter operand: -9 Enter operator: k Sorry, k, is not a valid operator. Please re-enter operator. Enter operator: MC 0 -> M Enter operator: + Enter operand: 3 -9 + 3 = -6 Enter operator: X Good bye.
修复后的完整脚本
#!/usr/bin/env bash # 显示用户说明 echo "Welcome to the Simple Calculator" echo "Instructions:" echo "Enter operand: Any digit (including negative), MR, MC, Clear (C), Off (X)" echo "Enter operator: +, -, *, /, MS, M+, MC, Clear (C), Off (X)" echo "------------------------------------------" # 初始化变量 result=0 memory=0 # 获取操作数的函数 get_operand() { local input while true; do read -p "Enter operand: " input case "$input" in # 支持正数和负数格式 -[0-9]*|[0-9]*) echo "$input"; break;;; "MR") echo "$memory"; echo "M -> $memory"; break;;; "MC") memory=0; echo "0 -> M";; "C") result=0; echo "results cleared";; "X") echo "Good bye."; exit 0;; *) echo "Invalid input. Please re-enter operand." esac done } # 获取运算符的函数 get_operator() { local input while true; do read -p "Enter operator: " input case "$input" in "+"|"-"|"*"|"/") echo "$input"; break;;; "MS") memory="$result"; echo "$result -> M"; break;; "M+") local prev_mem=$memory memory=$((memory + result)) echo "$result + $prev_mem = $memory -> M" break;; "MC") memory=0; echo "0 -> M"; break;; "C") result=0; echo "results cleared"; break;; "X") echo "Good bye."; exit 0;; *) echo "Sorry, $input, is not a valid operator. Please re-enter operator." esac done } # 初始操作数输入 result=$(get_operand) while true; do operator=$(get_operator) # 处理非算术运算符,无需后续操作数,直接回到运算符输入 case "$operator" in "MS"|"M+"|"MC"|"C") continue;; esac # 循环获取有效的数值操作数,跳过MC/C等非数值返回 while true; do operand=$(get_operand) if [[ "$operand" =~ ^-?[0-9]+$ ]]; then break fi done prev_result="$result" case "$operator" in "+") result=$((result + operand));; "-") result=$((result - operand));; "*") result=$((result * operand));; "/") if [ "$operand" -eq 0 ]; then echo "Can't divide by zero. Please re-enter divisor." continue fi result=$((result / operand)) ;; esac echo "$prev_result $operator $operand = $result" done
关键修复说明
- 支持负数操作数:在
get_operand的正则匹配中添加-[0-9]*,兼容负数输入。 - 修正非算术操作流程:主循环中判断如果是
MS/M+/MC/C这类无需操作数的指令,直接跳过获取操作数步骤,避免无效输入请求。 - 操作数有效性校验:添加数值格式检查,确保只有合法的正负整数会被用于计算,排除执行MC/C后的空返回值。
- 对齐预期输出格式:
- MR操作时显示
M -> 数值的提示 - M+操作显示完整的内存计算过程
- 无效运算符提示包含具体错误运算符名称
- MR操作时显示
- 修复初始计算逻辑:调整主循环流程,确保算术操作严格遵循「操作数→运算符→操作数→计算输出」的流程。
内容的提问来源于stack exchange,提问作者Ahmed Dildar
相关产品推荐
相关产品推荐

