首页 > 试题广场 >

计算器

[编程题]计算器
  • 热度指数:829 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 40M,其他语言80M
  • 算法知识视频讲解
输入为一个算数表达式的字符串。输出它经过计算之后的结果。如果该字符串不满足算数表达式则输出字符串Error。
注意:
0. 输入中的数只有非负整数。小数、负数等均需要输出Error。
1. 需要支持运算符加、减、乘以及括号。
2. 运算符的优先级为:括号>加=减>乘。
3. 支持数与操作符、操作符与操作符之间有任意空格。
3. 输入和运算过程中不需要考虑整数溢出,用32位的int即可。

输入描述:
输入1:123
输入2:1 23
输入3:1 + 2 * 3
输入4:1+(2*3)


输出描述:
输出1:123
输出2:Error
输出3:9
输出4:7
示例1

输入

1 + 2 * 3 - (4*5)

输出

-51

说明

1 + 2 * 3 - (4*5)   =>  1 + 2 * 3 - 20   => 3 * 3 - 20  =>  3 * -17  =>  -51  
参考了前面那位用Python写的大神的,加了自己错的地方的批注
s = input()
ops = []
nums = []
def check(s):
    if s.count('(')!=s.count(')'):
        return False
    elif '.' in s:
        return False
    else:
            i = s.find(' ')
            if i!=-1:
                if s[i+1].isdigit() and s[i-1].isdigit():
                        return False
            s = s.strip()
            for i in range(len(s)):
                if s[i] in '+-*/':
                    if i-1<0:
                        return False
                    else:
                        if s[i-1] in '+-*/':
                            return False
    return True
    
def compute(ops, nums):
    sec = nums.pop()  #这是后面的数
    fir = nums.pop()  
    op = ops.pop()
    nums.append(eval(str(fir) + op + str(sec)))

if not check(s):
    print('Error')
else:
    i = 0
    while i < len(s):
        if s[i] == ' ':
            i+=1    #这里后面要跳过,必须要在这里i+=1
            continue
        elif s[i] in '(+-*/':
            ops.append(s[i])
        elif s[i] == ')':
            while ops[-1]!='(':
                compute(ops, nums)
            ops.pop()
            if ops and ops[-1] in '+-':
                #如果最后是类似(3+5)这样的,要先判断ops是否为空才能计算
                compute(ops, nums)
        else:
            j = i + 1
            while j < len(s) and s[j].isdigit():
                j+=1
            nums.append(s[i:j]) #不需要用for循环,用切片!
            if ops and ops[-1] in '+-':
                #ops不空才计算
                compute(ops, nums)
            i = j - 1 #不用i+=1了,已经可以跳到j-1(最后一个数字)
        i+=1
    while len(ops)!=0:
        compute(ops,nums)
if nums:
    print(nums[0])

发表于 2021-07-29 18:30:45 回复(0)
def computer(nums, signs):
    """
    类后缀表达式计算
    :param nums:存储运算数
    :param signs:存储运算符
    :return:
    """
    a = nums.pop()
    b = nums.pop()
    sign = signs.pop()
    nums.append(eval(str(b) + sign + str(a)))


def check(s):
    """
    检查输入合法性
    :param s:
    :return:
    """
    if s.count('(') != s.count(')'):
        return False
    return True


def solve(s):
    if not check(s):
        return "Error"
    n = len(s)
    nums = []
    signs = []
    i = 0
    while i < n:
        if s[i] == ' ':
            i += 1
            continue
        if s[i] in '(+-*':
            signs.append(s[i])
        if s[i] == ')':
            while signs and signs[-1] != '(':  # 计算出括号中所有的 *
                computer(nums, signs)
            if signs and signs[-1] == '(':  # 删掉左括号
                signs.pop()
            if signs and signs[-1] != '(':  # 括号作为一个整体与前一个数字左运算
                computer(nums, signs)
        if '0' <= s[i] <= '9':
            j = i
            while j < n and '0' <= s[j] <= '9':
                j += 1
            nums.append(int(s[i:j]))
            if signs and signs[-1] == '+':
                computer(nums, signs)
            if signs and signs[-1] == '-':
                computer(nums, signs)
            i = j - 1
        i += 1
    while len(nums) > 1 and signs:
        computer(nums, signs)
    if len(nums) == 1 and not signs:
        return nums[0]
    else:
        return "Error"


def main():
    s = input()
    print(solve(s))


def test():
    s = "(123)-4567 +4)"
    print(solve(s))
    print(solve("1 + 2 * 3 - (4*5)"))


main()

发表于 2019-05-21 21:11:13 回复(0)
str1 = input().replace('\n', '').replace('\r', '')


# 得到表达式的形式列表
def get_num_list(str1):
    if '.' in str1 or '/' in str1 or str1.count('(') != str1.count(')'):
        print('Error')
        return []

    计数括号 = 0
    计数括号开始位置 = 0
    计数括号结束位置 = 0
    形式列表 = []
    # 从左往右开始计数
    while (1):
        if '(' not in str1 and '+' not in str1 and '-' not in str1 and '*' not in str1:
            if str1.replace(' ','') != '':
                形式列表.append(str1)
            break
        count = len(str1)
        for i in range(0, count):
            if 计数括号 == 0 and str1[i] in '+-*':
                #前面一个元素属于列表
                if str1[0:i].replace(' ','')!='':
                    形式列表.append(str1[0:i])
                形式列表.append(str1[i])
                str1 = str1[i + 1:]
                break
            elif str1[i] == '(':
                计数括号 = 计数括号 + 1
                if 计数括号 == 1:
                    计数括号开始位置 = i
            elif str1[i] == ')':
                计数括号 = 计数括号 - 1
                if 计数括号 == 0:
                    计数括号结束位置 = i
                    # 将此表达式截取 继续递归 并且加入到列表中
                    形式列表.append(get_num_list(str1[计数括号开始位置 + 1:计数括号结束位置]))
                    str1 = str1[计数括号结束位置 + 1:]
                    break
    return 形式列表


# 计算形式列表
def count_表达式(形式列表):
    if len(形式列表) == 0:
        return
    else:
        while(1):
            judge = 0
            # 先计算括号内的  也就是列表中的下级子列表
            for ele in range(len(形式列表)):
                if isinstance(形式列表[ele], list):
                    judge = 1
                    形式列表[ele] = count_表达式(形式列表[ele])
                    break
            if judge == 0 :
                break
        while(1):
            judge = 0
            # 计算加号,找到加号前后2个元素  计算后 替换掉原有的3个元素位置
            for ele in range(len(形式列表)):
                if 形式列表[ele] == '+':
                    judge = 1
                    # 这里的判断直接封装(+-*通用)
                    try:
                        元素前 = 形式列表[ele - 1]
                        元素后 = 形式列表[ele + 1]
                        新元素 = int(元素前) + int(元素后)
                        形式列表[ele] = 新元素
                        形式列表.remove(元素前)
                        形式列表.remove(元素后)
                        break
                    except Exception as e:
                        # 这里解决了  空格 等很多问题
                        print('Error')
                        return
                if 形式列表[ele] == '-':
                    judge = 1
                    # 这里的判断直接封装(+-*通用)
                    try:
                        元素前 = 形式列表[ele - 1]
                        元素后 = 形式列表[ele + 1]
                        新元素 = int(元素前) - int(元素后)
                        形式列表[ele] = 新元素
                        形式列表.remove(元素前)
                        形式列表.remove(元素后)

                        break
                    except Exception:
                        # 这里解决了  空格 等很多问题
                        print('Error')
                        return
            if judge == 0 :
                break
        while(1):
            judge = 0
            for ele in range(len(形式列表)):
                if 形式列表[ele] == '*':
                    # 这里的判断直接封装(+-*通用)
                    try:
                        judge = 1
                        元素前 = 形式列表[ele - 1]
                        元素后 = 形式列表[ele + 1]
                        新元素 = int(元素前) * int(元素后)
                        形式列表[ele] = 新元素
                        形式列表.remove(元素前)
                        形式列表.remove(元素后)
                        break
                    except Exception:
                        # 这里解决了  空格 等很多问题
                        print('Error')
                        return
            if judge == 0 :
                break
                        # 肯定返回的是一个结果,将这个数值直接放入原来的列表中,一层层去掉括号
        try:
            rep = int(形式列表[0])
        except Exception:
            print('Error')
            return
    return rep
num1 = get_num_list(str1)

num= count_表达式(num1)
if num:
    print(num)

#递归写的 超时了 第10个例子
发表于 2021-11-16 19:05:37 回复(0)
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int getOpsType(char s){
    return s=='('?7:s==')'?6:s == '+'?5:s=='-'?4:s=='*'?3:s=='/'?2:1;
}

int cal(int num1, int num2, int ops) {
    int ret = 0;
    switch(ops){
    case 5 :
        ret = num1 + num2;
        break;
    case 4:
        ret = num2 - num1;
        break;
    case 3:
        ret = num1 * num2;
        break;
    case 2:
        ret = num2 / num1;
        break;
    default:
        break;  
    }
    return ret;
}
void calculator(stack<int>& stack_ops,stack<int>& stack_num){
    int ops = stack_ops.top();
    stack_ops.pop();
    int num1 = stack_num.top();
    stack_num.pop();
    int num2 = stack_num.top();
    stack_num.pop();
    stack_num.push(cal(num1, num2, ops));
}

int main() {
    string s;
    stack<int> stack_ops = stack<int>();
    stack<int> stack_num = stack<int>();
    while (getline(cin,s)) {
        int start = 0;
        int curSt = 0;
        int preOpsType = 0;
        bool isCheckOps = false;
        for(int i=0;i<s.size();i++){
            if(s[i] == '.'){
                cout <<"Error"<< endl;
                return 0;
            }
            if(s[i] != ' '){
                int curOpsType = getOpsType(s[i]);
                if(curOpsType>1){
                    if(curOpsType==4&&preOpsType!=1&&preOpsType!=-1){
                        isCheckOps = true;
                        continue;
                    }
                    if(curOpsType>1&&curOpsType<6&&preOpsType>1&&preOpsType<6){
                        cout <<"Error"<< endl;
                        return 0;
                    }
                    preOpsType = curOpsType;
                    if(curOpsType == 7){
                        stack_ops.push(curOpsType);
                        curSt++;
                        preOpsType = 0;
                    }
                    else if(curOpsType == 6){
                        if(stack_ops.empty()){
                            cout <<"Error"<< endl;
                            return 0;
                        }
                        while(true){
                            if(stack_ops.top()==7) {
                                break;
                            }
                            calculator(stack_ops,stack_num);
                            if(stack_ops.empty()){
                                cout <<"Error"<< endl;
                                return 0;
                            }
                        }
                        stack_ops.pop();
                        curSt--;
                        preOpsType = -1;
                    }
                    else if(stack_ops.empty()){
                        stack_ops.push(curOpsType);
                    }
                    else if(curOpsType/2 <= stack_ops.top()/2&&stack_ops.top()/2 !=3){
                        calculator(stack_ops,stack_num);
                        stack_ops.push(curOpsType);
                    }
                    else{
                        stack_ops.push(curOpsType);
                    }
                }
                else{
                    start = i;
                    int spNum = 0;
                    while(true){
                        i++;
                        if(i == s.size() || getOpsType(s[i])>1){
                            i--;
                            break;
                        }
                        if(s[i] == ' '){
                            spNum++;
                            break;
                        }
                    }
                    //不能连续两个数字
                    if(preOpsType == 1){
                        cout <<"Error"<< endl;
                        return 0;
                    }
                    int num = stoi(s.substr(start,i - start + 1 - spNum));
                    if(isCheckOps){
                        if(preOpsType == 4)
                            num=-num;
                        isCheckOps = false;
                    }
                    stack_num.push(num);
                    preOpsType = curOpsType;
                }
            }
        }
        if(curSt != 0||isCheckOps){
            cout <<"Error"<< endl;
            return 0;
        }
        while(true){
            if(stack_ops.empty()) {
                break;
            }
            calculator(stack_ops,stack_num);
        }
        cout << to_string(stack_num.top())  << endl;
    }
    return 0;
}


编辑于 2021-08-22 19:57:57 回复(0)
最垃圾的解法。。。自己纯敲出来的。。。没用到stack。。。超过了0%
public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String inStr = sc.nextLine();
        //判断是否存在两个数字中间有空格的情况
        if(inStr.matches(".*\\d+\\s+\\d+.*")){
            System.out.println("Error");
            return;
        }
        String operation = inStr.replaceAll("\\s*", "");
        //判断字符串是否有多余正负号
        if(operation.matches(".*[+\\-*(][+\\-*].*")){
            System.out.println("Error");
            return;
        }
        //计算圆括号是否都能配对
        int countLeft = 0;
        char[] opOnlyBracket = operation.replaceAll("[\\s\\d\\-+*]", "").toCharArray();
        for (char c : opOnlyBracket) {
            if ('(' == c) {
                countLeft++;
            }
        }
        if(countLeft != opOnlyBracket.length - countLeft){
            System.out.println("Error");
            return;
        }
        //计算除了+ - * ( ) 与整数外是否还存在其他符号,不允许出现
        String otherStr = operation.replaceAll("[\\s\\d\\-+*()]", "");
        if(otherStr.length() > 0){
            System.out.println("Error");
            return;
        }
        //判断如果仅仅是输入了一个数字,则直接返回数字
        if(operation.matches("[+|-]?\\d+")){
            System.out.println(Integer.parseInt(operation));
            return;
        }

        System.out.println(sumCount(operation));
    }

    private static int sumCount(String operation){
        if(operation.matches("[+|-]?\\d") || operation.matches("\\(+\\d+\\)+")){
            return Integer.parseInt(operation.replaceAll("[()]",""));
        }

        while(operation.contains("(")){
            String bracketOp = operation.substring(operation.lastIndexOf("(")+1);
            String inner = bracketOp.substring(0,bracketOp.indexOf(")"));
            String innerBracket = "(" + inner + ")";
            operation = operation.replace(innerBracket, String.valueOf(dealPerOperation(inner)));
        }
//        else if(operation.contains("(")){
//            String bracketOp = operation.substring(operation.lastIndexOf("(")+1);
//            String inner = bracketOp.substring(0,bracketOp.indexOf(")"));
//            int count = dealPerOperation(inner);
//            operation = operation.replace("(" + inner + ")", ""+ count);
//            return sumCount(operation);
//        }
        return dealPerOperation(operation);

    }

    private static int dealPerOperation(String operation){
        if(operation.contains("*")){
            int count = 1;
            for(String s : operation.split("\\*")){
                count = count * sumNum(s);
            }
            return count;
        }
        return sumNum(operation);
    }

    private static int sumNum(String operationIn) {
        String operation = ("+" + operationIn).replace("--", "+").replace("+-", "-");
        String operation2 = operation.replaceAll("\\d", "");
        String[] nums = operation.split("[+\\-]");
        int count = 0;
        for (int i = 0; i < operation2.length(); i++) {
            if (operation2.charAt(i) == '+') {
                count = count + Integer.parseInt(nums[i+1]);
            } else {
                count = count - Integer.parseInt(nums[i+1]);
            }
        }
        return count;
    }


发表于 2021-04-16 20:41:14 回复(0)
为什么这个是这样?

发表于 2021-04-03 17:07:37 回复(0)
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;
 
bool subCheck1(string& s);
string subCheck2(string& s);  //去除所有括号
bool CheckAndModify(string& s);
string Calculate(string& s);
int dfs(string& s, int& i);
int priority(char ch);
int docalculate(long long n1, long long n2, char op);
 
 
bool subCheck1(string& s)  //检查括号
{
    stack<char> st;
    for (int i = 0; i < s.size(); i++)
    {
        if (s[i] == '(')
            st.push(s[i]);
        else if (s[i] == ')')
        {
            if (st.empty() || st.top() != '(')
                return false;
            st.pop();
        }
    }
    return st.empty();
}
 
string subCheck2(string &s)  //去除所有括号
{
    int index = 0;
    string ret;
    for (int i = 0; i < s.size();)
    {
        if (s[i] == '(' || s[i] == ')')
            i++;
        else
            ret.push_back(s[i++]);
    }
    return ret;
}
 
bool CheckAndModify(string& s)
{
    int bpos = s.find(' ');
    int epos = bpos;
    while (epos < s.size() && s[epos] == ' ')
        epos++;
    if (bpos != string::npos && isdigit(s[bpos - 1]) && isdigit(s[epos]))  //1 23情况
        return false;
    int index = 0;
    for (int i = 0; i < s.size();)  //去除空格
    {
        if (s[i] == '.')  //小数情况
            return false;
        if (s[i] == ' ')
        {
            i++;
        }
        else
        {
            s[index++] = s[i++];
        }
    }
    s.resize(index);
    if (!subCheck1(s))  //检查括号
        return false;
 
    string ret = subCheck2(s);
    for (int i = 0; i < ret.size(); i++)
    {
        if (!isdigit(ret[i]))
        {
            if (i - 1 >= 0 && !isdigit(ret[i - 1]))
                return false;
            if (i + 1 < ret.size() && !isdigit(ret[i + 1]))
                return false;
        }
    }
    return true;
}
 
 
string Calculate(string& s)
{
    if (s.empty())
        return "Error";
    if (!CheckAndModify(s))
        return "Error";
    int i = 0;
    int res = dfs(s,i);
    return to_string(res);
}
int dfs(string &s,int &i)
{
    int res = 0;
    stack<int> nums;
    stack<char> op;
    for (; i < s.size(); i++)
    {
        if (s[i] == '(')
        {
            nums.push(dfs(s, ++i));
        }
        else if (s[i] == ')')
        {
            while (!op.empty())
            {
                int num2 = nums.top();
                nums.pop();
                int num1 = nums.top();
                nums.pop();
                int tmp = docalculate(num1, num2, op.top());
                op.pop();
                nums.push(tmp);
            }
            res += nums.top();
            return res;
        }
        else if (isdigit(s[i]))
        {
            int cur = 0;
            while (i < s.size() && isdigit(s[i]))
            {
                cur = cur * 10 + s[i] - '0';
                i++;
            }
            i--;
            nums.push(cur);
        }
        else
        {
            while (!op.empty() && priority(op.top()) >= priority(s[i]))
            {
                int num2 = nums.top();
                nums.pop();
                int num1 = nums.top();
                nums.pop();
                int tmp = docalculate(num1, num2, op.top());
                op.pop();
                nums.push(tmp);
            }
            op.push(s[i]);
        }
    }
    while (!op.empty())
    {
        int num2 = nums.top();
        nums.pop();
        int num1 = nums.top();
        nums.pop();
        int tmp = docalculate(num1, num2, op.top());
        op.pop();
        nums.push(tmp);
    }
    res += nums.top();
    return res;
}
 
int priority(char ch)
{
    if (ch == '+' || ch == '-') return 2;
    else if (ch == '*') return 1;
    else return 0;
}
 
int docalculate(long long n1, long long n2, char op)
{
    int res = 0;
    switch (op)
    {
    case '+':
        res = n1 + n2;
        break;
    case '-':
        res = n1 - n2;
        break;
    case '*':
        res = n1 * n2;
        break;
    }
    return res;
}
 
int main()
{
    string s;
    vector<string> res;
    while (getline(cin,s))
    {
        string str = Calculate(s);
        res.emplace_back(move(str));
    }
    for (auto str : res)
        cout << str << endl;
    return 0;
}

发表于 2019-09-22 23:05:24 回复(0)
优先判断合法性,使用check函数检测出错误情况,直接输出error,在不会其他计算器的情况下先保证在自己的ac>0
import sys

def prior(s):
    if s in ['+','-']:
        return 1
    if s in ['*','/']:
        return 0
    if s in ['(']:
        return -1

def RPN(lst):
    n=len(lst)
    if n==1:
        return int(lst[0])
    res=0
    cal=[]
    for i in range(n):
        if lst[i] in ['+','-','*','/']:
            b=cal.pop()
            a=cal.pop()
            sign=lst[i]
            if sign == '+':
                res = int(a) + int(b)
            elif sign == '-':
                res = int(a) - int(b)
            elif sign == '*':
                res = int(a) * int(b)
            elif sign == '/':
                res = int(a) / int(b)
            cal.append(res)
        else:
            cal.append(int(lst[i]))
    return cal.pop()



def solve(s):
    vector=[]
    stack=[]
    n=len(s)
    temp=''
    for i in range(n):
        if s[i]==' ':
            continue
        if s[i].isdigit():
            temp+=s[i]
            if i==n-1:
                vector.append(temp)
        else:
            if temp.isdigit():
                vector.append(temp)
            temp=''
            if len(stack)==0:
                stack.append(s[i])
            else:
                if s[i]=='(' :
                    stack.append(s[i])
                elif s[i]==')':
                    while len(stack)>0 and stack[-1]!='(':
                        vector.append(stack.pop())
                    stack.pop()
                elif prior(s[i])>prior(stack[-1]):
                    stack.append(s[i])
                elif prior(s[i])<=prior(stack[-1]):
                    while len(stack)>0 and prior(s[i])<=prior(stack[-1]):
                        vector.append(stack.pop())
                    stack.append(s[i])
    while len(stack)>0:
        vector.append(stack.pop())
    return vector

def check(s):
    n=len(s[:-1])
    flag=''
    for i in range(n):
        if s[i]>='0' and s[i]<='9':
            flag+='0'
        elif s[i]==' ':
            flag+='1'
        elif s[i] in '+-*/':
            flag+='2'
        elif s[i] in'()':
            flag+='3'
        else:
            flag+='4'
    return flag


if __name__ =='__main__':

    for line in sys.stdin:

        if line.count('(')!=line.count(')'):
            print('Error')
        else:
            if '010' in check(line):
                print('Error')
            elif '22' in check(line):
                print('Error')
            else:
                res=solve(line[:-1])
                ans=RPN(res)
                print(ans)



发表于 2019-08-27 15:11:10 回复(0)