// A program to implement a calculator accepting parentheses
#include // For stream input/output
#include // For the exit() function
#include // For the isdigit() function
#include // For the strcpy() function
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
void eatspaces(char* str); // Function to eliminate blanks
double expr(char* str); // Function evaluating an expression
double term(const char* str, size_t& index); // Function analyzing a term
double number(const char* str, size_t& index); // Function to recognize a number
char* extract(const char* str, size_t& index); // Function to extract a substring
const size_t MAX{ 80 }; // Maximum expression length, including '\0'
int main()
{
char buffer[MAX] {}; // Input area for expression to be evaluated
cout << endl
<< "Welcome to your friendly calculator."
<< endl
<< "Enter an expression, or an empty line to quit."
<< endl;
for (;;)
{
cin.getline(buffer, sizeof buffer); // Read an input line
eatspaces(buffer); // Remove blanks from input
if (!buffer[0]) // Empty line ends calculator
return 0;
try
{
cout << "\t= " << expr(buffer) // Output value of expression
<< endl << endl;
}
catch (const char* pEx)
{
cerr << pEx << endl;
cerr << "Ending program." << endl;
return 1;
}
}
}
// Function to eliminate spaces from a string
void eatspaces(char* str)
{
size_t i{}; // 'Copy to' index to string
size_t j{}; // 'Copy from' index to string
while ((*(str + i) = *(str + j++)) != '\0') // Loop while character
// copied is not \0
if (*(str + i) != ' ') // Increment i as long as
i++; // character is not a space
return;
}
// Function to evaluate an arithmetic expression
double expr(char* str)
{
double value{}; // Store result here
size_t index{}; // Keeps track of current character position
value = term(str, index); // Get first term
for (;;) // Indefinite loop, all exits inside
{
switch (*(str + index++)) // Choose action based on current character
{
case '\0': // We're at the end of the string
return value; // so return what we have got
case '+': // + found so add in the
value += term(str, index); // next term
break;
case '-': // - found so subtract
value -= term(str, index); // the next term
break;
default: // If we reach here the string
char message[38] {"Expression evaluation error. Found: "};
strcat(message, str + index - 1); // Append the character
throw message;
break;
}
}
}
// Function to get the value of a term
double term(const char* str, size_t& index)
{
double value{}; // Somewhere to accumulate
// the result
value = number(str, index); // Get the first number in the term
// Loop as long as we have a good operator
while (true)
{
if (*(str + index) == '*') // If it's multiply,
value *= number(str, ++index); // multiply by next number
else if (*(str + index) == '/') // If it's divide,
value /= number(str, ++index); // divide by next number
else
break;
}
return value; // We've finished, so return what
// we've got
}
// Function to recognize a number in a string
double number(const char* str, size_t& index)
{
double value{}; // Store the resulting value
if (*(str + index) == '(') // Start of parentheses
{
char* psubstr{}; // Pointer for substring
psubstr = extract(str, ++index); // Extract substring in brackets
value = expr(psubstr); // Get the value of the substring
delete[]psubstr; // Clean up the free store
return value; // Return substring value
}
// There must be at least one digit...
if (!isdigit(*(str + index)))
{ // There's no digits so input is junk...
char message[31] {"Invalid character in number: "};
strcat(message, str + index); // Append the character
throw message;
}
while (isdigit(*(str + index))) // Loop accumulating leading digits
value = 10 * value + (*(str + index++) - '0');
// Not a digit when we get to here
if (*(str + index) != '.') // so check for decimal point
return value; // and if not, return value
double factor{ 1.0 }; // Factor for decimal places
while (isdigit(*(str + (++index)))) // Loop as long as we have digits
{
factor *= 0.1; // Decrease factor by factor of 10
value = value + (*(str + index) - '0')*factor; // Add decimal place
}
return value; // On loop exit we are done
}
// Function to extract a substring between parentheses
// (requires cstring)
char* extract(const char* str, size_t& index)
{
char* pstr{}; // Pointer to new string for return
int numL{}; // Count of left parentheses found
size_t bufindex{ index }; // Save starting value for index
do
{
switch (*(str + index))
{
case ')':
if (0 == numL)
{
++index;
pstr = new char[index - bufindex];
if (!pstr)
{
throw "Memory allocation failed.";
}
strcpy(pstr, str + bufindex); // Copy substring to new memory
return pstr; // Return substring in new memory
}
else
numL--; // Reduce count of '(' to be matched
break;
case '(':
numL++; // Increase count of '(' to be
// matched
break;
}
} while (*(str + index++) != '\0'); // Loop - don't overrun end of string
throw "Ran off the end of the expression, must be bad input.";
}
#include<stack> #include<iostream> #include<deque> #include<string> using namespace std; //判断是否为括号 bool isPra(char c) { if (c == '(' || c == ')') return true; else return false; } //获得符号的优先性 int getPri(char c) { switch (c) { case '+': case '-': return 0; //如果是加减,返回0 break; case '*': case '/': return 1; //如果是乘除,返回1 break; case '(': case ')': return -1; //注意,这里将括号设为最低优先级,因此括号不会被弹出,除非遇到右括号 break; } } //判断符号的优先性 void check(char c, stack<char> &coll2, deque<char> &coll3) { if (coll2.empty()) { coll2.push(c); return; } if (isPra(c)) { if (c == '(') coll2.push(c); else { //弹出所有元素直到遇到左括号 while (coll2.top() != '(') { char ch = coll2.top(); coll3.push_back(ch); coll2.pop(); } //当遇到左括号时,弹出但不加入coll3(后缀表达式中) coll2.pop(); } } else //如果不是括号 { //取出栈顶元素,与当前符号进行优先性比较 char sym = coll2.top(); //比较两符号的优先性 if (getPri(c) <= getPri(sym)) { //如果c的优先性比栈顶符号小或等于,弹出栈顶元素 coll2.pop(); //并将其压入coll3(后缀表达式)中 coll3.push_back(sym); //递归调用check,比较当前符号c与下一个栈顶符号的优先性 check(c, coll2, coll3); } else { //如果c比栈顶符号优先级大,那将c压入coll2(操作符栈)中 coll2.push(c); } } } //从coll中取出元素,分配元素到coll2和coll3中 void allocate(deque<char> &coll1, stack<char> &coll2, deque<char> &coll3) { while (!coll1.empty()) { char c = coll1.front(); coll1.pop_front(); if (c >= '0' && c <= '9') { coll3.push_back(c); } else { //调用check函数,针对不同情况作出不同操作 check(c, coll2, coll3); } } //如果输入结束,将coll2的元素全部弹出,加入后缀表达式中 while (!coll2.empty()) { char c = coll2.top(); coll3.push_back(c); coll2.pop(); } } //计算后缀表达式 void calculate(deque<char> &coll3, stack<int> &coll4) { while (!coll3.empty()) { char c = coll3.front(); coll3.pop_front(); //如果是操作数,压入栈中 if (c >= '0' && c <= '9') { //减去'0'得出偏移值,即为真实数值(如果直接转换成int,结果不对,因为char 转换为int是其编码值,例如'1'的编码值为49 int op = c - '0'; coll4.push(op); } else //如果是操作符,从栈中弹出元素进行计算 { int op1 = coll4.top(); coll4.pop(); int op2 = coll4.top(); coll4.pop(); switch (c) { case '+': coll4.push(op2 + op1); break; case '-': coll4.push(op2 - op1); break; case '*': coll4.push(op2 * op1); break; case '/': coll4.push(op2 / op1); //注意是op2(op)op1而不是op1(op)op2 break; } } } } int main() { deque<char> coll1; //盛放中缀表达式 stack<char> coll2; //盛放操作符 deque<char> coll3; //盛放后缀表达式 stack<int>coll4; //计算后缀表达式的辅助容器 string str; cout << "请输入表达式,按enter结束:" << endl; cin >> str; for (int i = 0; i != str.size(); ++i) { //逐一加入每个字符,这里使用deque因为deque在两端删除添加的速度最快 coll1.push_back(str[i]); } //从coll中取出元素,分配元素到coll2和coll3中 allocate(coll1, coll2, coll3); //计算后缀表达式 calculate(coll3, coll4); cout << "计算结果为:" << coll4.top() << endl; }