表达式求值解析(C++实现)
一、运行效果
Enter the expression(q to quit): 5+3
8.00
Next expression(q to quit): 2*(5/4+(2+1))
8.50
Next expression(q to quit): q
Bye!
二、函数分析
(1) main( )
读取用户的输入,检查输入是否有效;
然后使用ConvertEnd()和Compute()函数对其进行转换和计算;
继续读取输入,直到用户输入“q”退出;
使用setiosflags()和setprecision()将输出格式化为两位小数。
int main() {
string front;
vector<char> end;
// Read input
cout << "Enter the expression(q to quit): ";
while (getline(cin, front) && front[0] != 'q') {
if (!isdigit(front[0])) {
cout << "Please enter the correct expression:";
end.clear(); continue;
}
// Conver to the end format
ConvertEnd(front, end);
// Calculate the value
cout << setiosflags(ios::fixed) << setprecision(2);
cout << Compute(end) << endl;
end.clear();
cout << "Next expression(q to quit): ";
}
cout << "Bye!\n";
return 0;
}
(2)ConvertEnd( )
接受用户输入的中缀表示法并将其转换为后缀表示法;
它使用堆栈来跟踪中缀表示法中的运算符,
并根据操作顺序重新排列它们以生成后缀表示法
void ConvertEnd(const string & front, vector<char> & end) {
stack<char> s;
for (int i = 0; i < front.length(); i++) {
if (isdigit(front[i]) || front[i] == '.') end.push_back(front[i]);
else if (IsOp(front[i])) {
end.push_back(' ');
if (s.empty()) s.push(front[i]);
else if (front[i] == ')') {
while (s.top() != '(') {
end.push_back(s.top()); s.pop();
}
s.pop();
} else {
if (IsBig(front[i], s.top())) s.push(front[i]);
else {
while (!s.empty() && s.top() != '(' && !IsBig(front[i], s.top())) {
end.push_back(s.top()); s.pop();
}
s.push(front[i]);
}
}
}
}
while (!s.empty()) {
end.push_back(s.top()); s.pop();
}
}
(3)Compute( )
计算ConvertEnd()函数生成的后缀表达式;
它使用另一个堆栈来跟踪操作数和运算符,并将运算符应用于操作数以产生最终输出。
float Compute(const vector<char> & end) {
// Compute the value through the end format
stack<float> s;
for (int i = 0; i < end.size(); i++) {
if (isdigit(end[i])) {
float temp = 0;
i += FindValue(temp, end, i);
s.push(temp);
} else if (IsOp(end[i])) {
s.push(SigComp(TopFloat(s), TopFloat(s), end[i]));
}
}
if (!s.empty()) {
return s.top();
} else { cout << "Error!\n"; return 0; }
}
(4)IsOp( )
检查给定字符是否为运算符;
( ‘+’、 ‘-’、 ‘*’、 ‘/’、 ‘(’ 、 ‘)’ )
bool IsOp(char ch) {
return (ch == '+') || (ch == '-')
|| (ch == '*') || (ch == '/')
|| (ch == '(') || (ch == ')');
}
(5)IsBig( )
检查一个运算符的优先级是否大于另一个。
它用于确定从中缀表示法转换为后缀表示法时应重新排列运算符的顺序。
bool IsBig(char ch0, char ch1) {
switch (ch0) {
case '+':
case '-': return false;
break;
case '/':
case '*': return (ch1 == '+') || (ch1 == '-');
break;
case '(': return (ch1 == '+') || (ch1 == '-')
|| (ch1 == '*') || (ch1 == '/');
break;
default: cout << "Error!" << endl;
return false;
}
}
(6)FindValue( )
在给定的字符数组中查找计算数值(整数或小数)的值
int FindValue(float & value, const vector<char> & arr, int start) {
int i, j, p; value = 0;
bool isDecimal = false;
float integer = 0, decimal = 0;
for (i = start; i < arr.size() && (isdigit(arr[i]) || arr[i] == '.' || arr[i] == ' '); i++) {
if (arr[i] == ' ') break;
if (arr[i] == '.') { isDecimal = true; break; }
integer = (integer * 10) + (arr[i] - '0');
}
if (isDecimal == true) {
for (j = i + 1, p = -1; j < arr.size() && isdigit(arr[j]); j++) {
decimal += (arr[j] - '0') * pow(10.0, p);
p--;
}
}
value = integer + decimal;
return isDecimal ? j - start - 1 : i - start - 1;
}
(7)TopFloat()
返回浮点数堆栈中的顶部值。
float TopFloat(stack<float> & s) {
if (s.empty()) {
cout << "Error!\n";
return 0;
} else {
float temp = s.top(); s.pop();
return temp;
}
}
(8)SigComp( )
接受两个浮点数 ( x 和 y) 和一个op表示算术运算 ( ‘+’, ‘-’, ‘*’, ‘/’ ) 的字符运算符
然后执行相应的操作y并将结果作为 float 值返回
float SigComp(float x, float y, char op) {
switch (op) {
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
default: cout << "Error!\n";
return 0;
}
}
三、整体代码
#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstring>
#include <vector>
#include <string>
#include <stack>
using namespace std;
// Convert the infix expression entered by the
// user into a suffix expression
void ConvertEnd(const string & front, vector<char> & end);
// Calculate the final value based on the suffix
// expression from the ConvertEnd()
float Compute(const vector<char> & end);
// Return ture if ch equals
// '+' '-' '*' '/' '(' ')'
bool IsOp(char ch);
// Return ture if the proprity of ch0 is greater than ch1
bool IsBig(char ch0, char ch1);
// Read the number or decimal character after start and
// convert it to a numberical value
int FindValue(float & value, const vector<char> & arr, int star);
// Return the top value in float stack
// if the stack is not empty
float TopFloat(stack<float> & s);
// Preform a specified four arithmetic
// operation on x and y
float SigComp(float x, float y, char op);
int main() {
string front;
vector<char> end;
// Read input
cout << "Enter the expression(q to quit): ";
while (getline(cin, front) && front[0] != 'q') {
if (!isdigit(front[0])) {
cout << "Please enter the correct expression:";
end.clear(); continue;
}
// Conver to the end format
ConvertEnd(front, end);
// Calculate the value
cout << setiosflags(ios::fixed) << setprecision(2);
cout << Compute(end) << endl;
end.clear();
cout << "Next expression(q to quit): ";
}
cout << "Bye!\n";
return 0;
}
void ConvertEnd(const string & front, vector<char> & end) {
stack<char> s;
for (int i = 0; i < front.length(); i++) {
if (isdigit(front[i]) || front[i] == '.') end.push_back(front[i]);
else if (IsOp(front[i])) {
end.push_back(' ');
if (s.empty()) s.push(front[i]);
else if (front[i] == ')') {
while (s.top() != '(') {
end.push_back(s.top()); s.pop();
}
s.pop();
} else {
if (IsBig(front[i], s.top())) s.push(front[i]);
else {
while (!s.empty() && s.top() != '(' && !IsBig(front[i], s.top())) {
end.push_back(s.top()); s.pop();
}
s.push(front[i]);
}
}
}
}
while (!s.empty()) {
end.push_back(s.top()); s.pop();
}
}
bool IsOp(char ch) {
return (ch == '+') || (ch == '-')
|| (ch == '*') || (ch == '/')
|| (ch == '(') || (ch == ')');
}
bool IsBig(char ch0, char ch1) {
switch (ch0) {
case '+':
case '-': return false;
break;
case '/':
case '*': return (ch1 == '+') || (ch1 == '-');
break;
case '(': return (ch1 == '+') || (ch1 == '-')
|| (ch1 == '*') || (ch1 == '/');
break;
default: cout << "Error!" << endl;
return false;
}
}
float Compute(const vector<char> & end) {
// Compute the value through the end format
stack<float> s;
for (int i = 0; i < end.size(); i++) {
if (isdigit(end[i])) {
float temp = 0;
i += FindValue(temp, end, i);
s.push(temp);
} else if (IsOp(end[i])) {
s.push(SigComp(TopFloat(s), TopFloat(s), end[i]));
}
}
if (!s.empty()) {
return s.top();
} else { cout << "Error!\n"; return 0; }
}
int FindValue(float & value, const vector<char> & arr, int start) {
int i, j, p; value = 0;
bool isDecimal = false;
float integer = 0, decimal = 0;
for (i = start; i < arr.size() && (isdigit(arr[i]) || arr[i] == '.' || arr[i] == ' '); i++) {
if (arr[i] == ' ') break;
if (arr[i] == '.') { isDecimal = true; break; }
integer = (integer * 10) + (arr[i] - '0');
}
if (isDecimal == true) {
for (j = i + 1, p = -1; j < arr.size() && isdigit(arr[j]); j++) {
decimal += (arr[j] - '0') * pow(10.0, p);
p--;
}
}
value = integer + decimal;
return isDecimal ? j - start - 1 : i - start - 1;
}
float TopFloat(stack<float> & s) {
if (s.empty()) {
cout << "Error!\n";
return 0;
} else {
float temp = s.top(); s.pop();
return temp;
}
}
float SigComp(float x, float y, char op) {
switch (op) {
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
default: cout << "Error!\n";
return 0;
}
}