输入方法:复制你想计算的内容运行程序后自动计算
#include <iostream>
#include <Windows.h>
#include <string>
#include <math.h>
#include<cstdio>
#include<stack>
#include<string>
#include<cstring>
#include<cmath>
#include<ctype.h>
#pragma warning(disable:4996)
using namespace std;
string Return_the_content_of_the_clipboard() {
HANDLE hData = GetClipboardData(CF_TEXT); // 获取剪切板数据句柄
char* pszText = static_cast<char*>(GlobalLock(hData)); // 锁定内存并获取指向数据的指针
GlobalUnlock(hData); // 解锁内存
CloseClipboard(); // 关闭剪切板
string s1 = pszText;
return s1;
}
int OperatorPri(char opt)//将优先级量化便于比较
{
switch (opt)
{
case '#': return 0;
case ')': return 1;
case '|':
case '&': return 2;
case '-':
case '+': return 3;
case '*':
case '/': return 4;
case '!': return 5;
case '(': return 6;
default: return -1;
}
}
int PreOrder(char opt1, char opt2)//比较两个运算符的优先级
{
int i = OperatorPri(opt1);
int j = OperatorPri(opt2);
if (opt2 == '(') //( )内的 + - * / 还能进栈但是 + - * / 对应的数字小于 ( 对应的数字 所以把这里设置成 1 让()内的 + - * / 可以进栈
return 1;
if (i == -1 || j == -1)
return -1;
if (i > j)
return 1;
else if (i == j)
return 0;
else
return -1;
}
bool isOpr(char* p) //判断运算公式中的字符是不是数字
{
if (*p >= '0' && *p <= '9')
return true;
else return false;
}
char* getNum(char* p, int& num)//将char型字符换成数字
{
num = 0;
while (isOpr(p))
{
num = 10 * num + (*p - '0');
p++;
}
p--; //为了防止后面while循环中的p++跳过了运算符 !!!!!!!!!
return p;
}
int express(int e1, int e2, char opt) //运算
{
cout << e1 << opt << e2 << " is calculated!" << endl;
switch (opt)
{
case '+': return e1 + e2;
case '-': return e1 - e2;
case '*': return e1 * e2;
case '/': return e1 / e2;
case '&': return e1 && e2;
case '|': return e1 || e2;
case '!':return !e2; //逻辑非运算符是单目运算符要进行特殊处理(仅进行一个数的运算,另外一个出栈的数据在重新入栈)
default: cout << "wrong" << endl;
}
}
int Calc(char* s)
{
int x; //用来储存 express(e1,e2,opt) 要不然输出两边 cout<<e1<< opt <<e2<<" is calculated!"<<endl;
bool flag = false; //要用来判断最终两个栈是否为空
stack<char> opt; //用来储存运算符的栈
char c; //用来保存 get_top()数据
stack<int> opr; //用来储存数字的栈
int e1, e2, e; //用来保存 get_top e 用来压入数据
opt.push('#');
opr.push(1); //为了防止第一个运算符便是逻辑非(!运算符采用出栈两个数据进行一个数据的运算,另外一个重新入栈,这样便保持了单目运算符和双目运算符的一致性,而刚开始数据栈里面先储存个1,便是为了防止第一个运算符便是!的情况,1不参与任何的运算)
char* p = s; //初始化p
while (*p != '#')
{
if (isOpr(p)) //把字符转化为数字并入数字栈
{
p = getNum(p, e);
opr.push(e);
}
else //如果不是数字而是运算符,则对此运算符和栈顶运算符的优先级进行比较
{
c = opt.top();
if (PreOrder(*p, c) > 0) //当前入栈的运算符比栈顶的运算符优先级高则入栈
{
opt.push(*p);
}
else //当前入栈的运算符比栈顶的运算符优先级低则栈顶运算符出栈并出栈两个数据进行计算
{
opt.pop();
e1 = opr.top();
opr.pop();
e2 = opr.top();
opr.pop();
x = express(e2, e1, c);
if (c == '!') //若是逻辑非运算符,则只需要一个数据参与运算,另外一个数据再入栈
{
opr.push(e2);
}
opr.push(x); //结果入栈
if (*p == '+' || *p == '-' || *p == '*' || *p == '/' || *p == '&' || *p == '|' || *p == '!') //在进行了一次数据和运算符出栈计算后,*p对应的那个运算符还要继续进栈
{
opt.push(*p);
}
if (*p == ')')
{
c = opt.top(); //先判断这是否是个空括号
if (c != '(')
{
c = opt.top();
opt.pop();
e1 = opr.top();
opr.pop();
e2 = opr.top();
opr.pop();
x = express(e2, e1, c);
if (c == '!')
{
opr.push(e2);
}
opr.push(x);
c = opt.top();
opt.pop();
}
else
{
opt.pop();
}
}
}
}
p++;
}
if (*p == '#')
{
c = opt.top();
opt.pop();
e1 = opr.top();
opr.pop();
e2 = opr.top();
opr.pop();
x = express(e2, e1, c);
if (c == '!')
{
opr.push(e2);
}
opr.push(x);
c = opt.top();
opt.pop();
while (c != '#')
{
e1 = opr.top();
opr.pop();
e2 = opr.top();
opr.pop();
x = express(e2, e1, c);
if (c == '!')
{
opr.push(e2);
}
opr.push(x);
c = opt.top();
opt.pop();
}
e = opr.top();//最终结果
opr.pop();
cout << "结果:" << e << endl;
if (opt.empty() && opr.size() == 1) //数据栈中还有一个'1'没出栈
flag = true;
if (flag)
return e;
else
return -1;
}
}
int main()
{
string s1 = Return_the_content_of_the_clipboard();
char mychar[100] = {};
for (int i = 0; i < 100; i++)mychar[i] = s1[i];
cout << Calc(mychar) << endl;
return 0;
}