一、题目
输入算术表达式,可包含空格,检查算术表达式的合法性,若算术表达式不合法,打印错误类型,若合法,则进行运算,打印计算结果。
二、算法
1. 将输入的算术表达式字符串去除空格。
2. 检查输入的算术表达式的合法性,判断算式首字符是否合法(只能是前括号或正负号),判断括号是否匹配,判断连续字符是否合法(运算符后面可跟左括号,右括号后面可跟运算符,左括号后面可跟加减号表正负,左右括号之间不能直接相连,数字后面不能直接跟左括号)。
3. 构造符号栈和数据栈对合法的算术表达式进行计算,计算的过程就是从数据栈取出两个数据和符号栈取出一个数据,然后计算得到一个结果,再将结果压入数据栈。
三、代码
#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>
#include <vector>
#include <stack>
using namespace std;vector<char> g_opt = { '+', '-', '*', '/'};void RemoveSpaces(char* input)
{for (int i = 0; i < strlen(input); ++i){if (input[i] == ' '){for (int j = i; j < strlen(input); ++j){input[j] = input[j + 1];}--i;}}
}bool CheckInput(char* input)
{stack<char> bracket; // 用于判断括号的合法性for (int i = 0; i < strlen(input); ++i){if (!isdigit(input[i])){if (find(g_opt.begin(), g_opt.end(), input[i]) == g_opt.end()&& input[i] != '(' && input[i] != ')'){cout << "存在非法字符 " << input[i];return false;}if (input[i] == '('){bracket.push(input[i]);}else if (input[i] == ')'){if (bracket.empty()){cout << "括号不匹配";return false;}else{bracket.pop();}}// 第一个字符必须是数字或正负号或左括号if (i == 0 && input[i] != '+' && input[i] != '-' && input[i] != '('){cout << "首字符错误";return false;}if (!isdigit(input[i + 1])){if (input[i] == '('){// 左括号后面可以跟加减表示正负if (input[i + 1] == '*' || input[i + 1] == '/' || input[i + 1] == ')'){cout << "出现连续符号 " << input[i + 1];return false;}}else if (input[i] == ')'){// 有括号后面不能直接跟前括号,可以跟操作符if (input[i + 1] == '('){cout << "出现连续符号 " << input[i + 1];return false;}}else{// 操作符后面可以跟左括号if (input[i + 1] != '('){cout << "出现连续符号 " << input[i + 1];return false;}}}}else{// 数字后面不能直接跟左括号if (input[i + 1] == '('){cout << "括号位置错误 " << input[i + 1];return false;}}}if (!bracket.empty()){cout << "括号不匹配";return false;}return true;
}bool PopCal(stack<int>& datas, stack<char>& symbols)
{if (datas.size() < 2 || symbols.empty())return false;if (symbols.top() == '('){symbols.pop();return false;}int x = datas.top();datas.pop();int y = datas.top();datas.pop();char opt = symbols.top();symbols.pop();int res = (unsigned int)-1;if (opt == '+')res = x + y;else if (opt == '-')res = x - y;else if (opt == '*')res = x * y;else if (opt == '/')res = x / y;datas.push(res);return true;
}int Calculate(char* input)
{// 数据栈和符号栈stack<int> datas;stack<char> symbols;int flag = 1; // 1表示正,-1表示负数for (int i = 0; i < strlen(input); ++i){if (isdigit(input[i])){// 将连续数字字符转为整型数据存入数据栈string digit = "";digit += input[i];while (isdigit(input[i + 1])){++i;digit += input[i];}int num = atoi(digit.c_str());datas.push(num * flag);flag = 1;// 数据压栈后发现栈顶是乘除号,直接进行计算if (!symbols.empty() && (symbols.top() == '*' || symbols.top() == '/'))PopCal(datas, symbols);}else{// 左括号的优先级最高if (input[i] == '('){symbols.push(input[i]);continue;}// 判断负号if (i == 0 || input[i - 1] == '('){if (input[i] == '-')flag = -1;continue;}if (input[i] == '*' || input[i] == '/'){// 乘除符号直接压入符号栈symbols.push(input[i]);}else if (input[i] == '+' || input[i] == '-'){// 若符号栈存有加减号未计算,先计算再将加减号压栈if (!symbols.empty() && (symbols.top() == '+' || symbols.top() == '-')){PopCal(datas, symbols);}symbols.push(input[i]);}else if (input[i] == ')'){if (symbols.top() == '('){// 表示括号括住了数字,而不是表达式symbols.pop();}else{// 循环出栈计算,直到遇到左括号while (PopCal(datas, symbols)){}}}}}// 循环出栈计算while (PopCal(datas, symbols)){}return datas.top();
}int main()
{while (1){char input[128];cout << "请输入算术表达式:";fgets(input, sizeof(input), stdin);input[strlen(input) - 1] = 0;RemoveSpaces(input);if (strcmp(input, "exit") == 0)break;if (!CheckInput(input)){cout << ",表达式输入格式错误,请重新输入!" << endl;continue;}int res = Calculate(input);cout << input << " = " << res << endl;}return 0;
}