shell Linux中的简单计算器

cmssoen2  于 2023-10-23  发布在  Shell
关注(0)|答案(2)|浏览(94)

我试图创建一个简单的计算器使用bash脚本。面临的主要问题是,它不要求任何算术运算的第二个操作数。此外,它不适用于负数作为算术运算的操作数。请看下面的脚本。

#!/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:

以下是正确预期输出的示例序列:

$ ./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.

更新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

以下是错误的输出:

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:

更新2:我已经根据@Ed Morton在评论中提供的方法添加了其余的功能。以下是完整的脚本:

#!/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

但现在它显示的是不正确的运算结果,而不是算术运算。显示以下错误输出。

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:

预期根据上述共享示例序列(非穷举测试)获得正确的预期输出。

aiazj4mn

aiazj4mn1#

当前的问题似乎与一些不完整的逻辑有关,即何时请求新的operator和新的operand
在不尝试查看operand + operator的所有可能组合的情况下,使用OP的“正确预期输出”作为模板,在我看来,一般流程如下所示:

  • 首先得到一个操作数,然后进入一个循环,按照以下步骤...
  • 找个接线员
  • 根据运算符,要么 a) 得到另一个运算符,要么 b) 得到一个新的操作数
  • 如果我们选择得到一个新的操作数,然后执行所需的操作符/操作

高级伪代码设计:

get_operand

while true
do
    get_operator
    process_operator
        if operator == 'M+' || 'MC' then continue
    get_operand
    process_operand
    perform_operation_on_operand
done

显然,用read / case块替换get_*process_*调用(或者可能推入一对函数,使while true循环更清晰?).

dffbzjpn

dffbzjpn2#

我剥离了你的代码,只是让+工作。试试这个:

$ cat tst.sh
#!/usr/bin/env bash

# Initialize variables
result=0

# Function to get an operand
get_operand() {
    local input
    read -p "Enter operand: " input
    case "$input" in
        [0-9]*) ;;
        *) echo "Invalid input. Please re-enter operand."
           input=$(get_operand);;
    esac
    echo "$input"
}

# Function to get an operator
get_operator() {
    local input
    read -p "Enter operator: " input
    case "$input" in
        "+"|"-"|"*"|"/") ;;
        *) echo "Invalid operator. Please re-enter operator."
           input=$(get_operator);;
    esac
    echo "$input"
}

# Initial operand entry
result=$(get_operand)

while true; do
    operator=$(get_operator)

    operand=$(get_operand)

    prev_result="$result"
    case "$operator" in
        "+") result=$((result + operand));;
    esac

    echo "$prev_result $operator $operand = $result"
done

你会看到它的工作原理:

$ ./tst.sh
Enter operand: 4
Enter operator: +
Enter operand: 4
4 + 4 = 8
Enter operator:

现在将您的其他功能添加到它上面。
FWIW为了简单和清晰,我会在get_...函数中使用循环而不是递归,例如:

get_operand() {
    local input
    while [[ -z "$input" ]]; do
        read -p "Enter operand: " input
        case "$input" in
            [0-9]*) ;;
            *) echo "Invalid input. Please re-enter operand."
               input=""
        esac
    done
    echo "$input"
}

相关问题