根据文档;里的要求以及源码完成修改后的源码
时间: 2024-12-20 07:25:19 浏览: 15
根据文档的要求,以下是修改后的源码,已经实现了所需的功能并添加了必要的注释:
```cpp
#include<iostream>
#include<string>
#include<stdexcept>
#include<sstream>
#include<regex>
using namespace std;
// 节点类
class Node {
friend class LinkedStack; // 注意加上友元类 这样才能访问私有成员 注意格式 一定要加上class!
string data;
Node* next;
public:
Node(string datain = "") : data(datain), next(nullptr) {}
};
// 链栈类
class LinkedStack {
private:
Node* top; // 是不需要头节点的 因为插入删除都是在top这里
int numofelem;
public:
LinkedStack() : top(nullptr), numofelem(0) {} // 指针类型可以直接被赋值为0或nullptr 意思一样。这里不写成top=new Node() 是因为:创建一个空的栈时不需要立即创建一个Node对象 Node对象应该只在有元素被推入栈时才被创建。
bool IsEmpty() const { return top == nullptr; } // 注意const的使用
string GetTop() const;
int GetNum() const { return numofelem; }
void Add(string val);
string Delete();
// void Print() const;
};
// 获取栈顶元素
string LinkedStack::GetTop() const {
if (IsEmpty()) {
cout << "栈为空,无法获取栈顶元素!" << endl;
return "";
} else {
return top->data;
}
}
// 添加元素
void LinkedStack::Add(string val) {
Node* newNode = new Node(val);
newNode->next = top;
top = newNode;
numofelem++;
// cout << "添加后栈的元素有:";
// this->Print();
}
// 删除元素
string LinkedStack::Delete() {
if (IsEmpty()) {
cout << "栈为空,无法删除元素!" << endl;
return "";
}
Node* current = top;
string deletedata = current->data;
top = top->next;
delete current;
numofelem--;
// cout << "删除后栈的元素有:";
// this->Print();
return deletedata;
}
// 合法性检查
bool valid(string inputLine) {
// 判断符号后面有没有字母,类似3+4*这种情况,只需判断最后一个是不是符号(除了右括号)
char lastchar = inputLine[inputLine.length() - 1];
if (lastchar == '+' || lastchar == '-' || lastchar == '*' || lastchar == '/' || lastchar == '(') {
cout << "运算符后无数字或字母" << endl;
return false;
}
int leftkuohao = 0;
int rightkuohao = 0;
int countlianxu = 0;
int lastType = 0;
int chu0_situation = 0;
for (char ch : inputLine) {
if (ch == '(')
leftkuohao++;
else if (ch == ')')
rightkuohao++;
// 表达式不合法
if (!(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')')) {
cout << "表达式不合法!(输入了不合法字符,如%@#等)" << endl;
return false;
}
// 判断是否连续输入多个运算符(除了())
if (ch == '+' || ch == '-' || ch == '*' || ch == '/')
countlianxu++;
else if (ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '(' || ch == ')') {
if (countlianxu == 1)
countlianxu--;
}
if (countlianxu == 2) {
cout << "表达式不合法!(连续输入多个运算符,如1++a)" << endl;
return false;
}
// 判断是否存在数字字母之间没有运算符 解决这个问题首先要解决两位数字的问题
if (isdigit(ch)) {
if (lastType == 2) {
cout << "数字字母连续输入" << endl;
return false;
}
lastType = 1;
} else if (isalpha(ch)) {
if (lastType == 1) {
cout << "字母数字连续输入" << endl;
return false;
}
lastType = 2;
} else {
lastType = 0;
}
// 除数不为0
if (ch == '/') {
chu0_situation++;
} else if (chu0_situation == 1) {
if (ch == '0' || isalpha(ch))
chu0_situation++;
else
chu0_situation = 0;
}
if (chu0_situation == 2) {
cout << "除数不能为0和字母" << endl;
return false;
}
}
// 括号匹配
if (leftkuohao != rightkuohao) {
cout << "表达式不合法!(左右括号不匹配)" << endl;
return false;
}
return true;
}
// 运算符是否优先的判断
bool GAO(char ch, string top) {
// cout << "GAO中的ch:" << ch << endl << "top:" << top << endl;
if (ch == '+' && top == "+" || ch == '+' && top == "-" || ch == '-' && top == "+" || ch == '-' && top == "-" || top == "*" || top == "/")
return false;
else if (ch == '*' && top == "+" || ch == '/' && top == "+" || ch == '*' && top == "-" || ch == '/' && top == "-")
return true;
}
// 运算函数
string OPER(string num1, string yunsuanfu, string num2) {
// 检查 num1 是否为数字
bool isNum1Digit = true;
for (char c : num1) {
if (c < '0' || c > '9') {
isNum1Digit = false;
break;
}
}
// 检查 num2 是否为数字
bool isNum2Digit = true;
for (char c : num2) {
if (c < '0' || c > '9') {
isNum2Digit = false;
break;
}
}
// 如果 num1 和 num2 都是数字,则进行计算
if (isNum1Digit && isNum2Digit) {
int num1Int = stoi(num1); // 将字符串转换为整数
int num2Int = stoi(num2); // 将字符串转换为整数
ostringstream oss;
switch (yunsuanfu[0]) {
case '+':
oss << (num1Int + num2Int);
break;
case '-':
if (num1Int - num2Int < 0) {
// cout << "出现负数!" << endl;
return "";
}
oss << (num1Int - num2Int);
break;
case '*':
oss << (num1Int * num2Int);
break;
case '/':
// 这里是避免不了除数为0的情况的 比如:5/(2-2) 还是要在这里进行判断
if (num2Int == 0) {
// cout << "除数为0" << endl;
// cout << "aaaaaaaaaaaaaaaaaaaaaaaaa" << num2Int << "sssssssss" << endl;
return "!";
}
oss << static_cast<double>(num1Int) / static_cast<double>(num2Int);
break;
default:
break;
}
return oss.str(); // 返回计算结果的字符串
} else {
// 如果 num1 或 num2 中有一个不是数字,则返回运算式子
return num1 + " " + yunsuanfu + " " + num2;
}
}
// 判断字符串中是否有字母
bool containsLetter(const string& str) {
for (char ch : str) {
if (isalpha(ch)) { // 判断是否为字母
return true;
}
}
return false;
}
// 对SIGN栈的进入进入单独处理 有三种情况
void SIGNADD(LinkedStack& NUM, LinkedStack& SIGN, string singleCharString, char ch, int& fushuchuxian, int& chushu0) {
// 1.( 或者栈为空 直接进入
if (SIGN.IsEmpty() || ch == '(') {
SIGN.Add(singleCharString);
return;
}
// 2. ) 弹出计算直到弹出 对应(
else if (ch == ')') {
string popyunsuanfu = SIGN.Delete();
while (popyunsuanfu != "(") {
string num2 = NUM.Delete();
string num1 = NUM.Delete();
string result = OPER(num1, popyunsuanfu, num2);
if (result == "") {
// cout << "出现负数!" << endl;
fushuchuxian++;
return;
}
if (result == "!") {
// cout << "除数为0" << endl;
chushu0++;
return;
}
popyunsuanfu = SIGN.Delete();
NUM.Add(result);
}
// 怎么实现括号加到result上?:把top取出来,如果里面含有字母的话就加上括号
string result = NUM.GetTop();
NUM.Delete();
if (containsLetter(result)) {
if (SIGN.GetTop() == "/") {
chushu0++;
return;
}
result = '(' + result + ')';
NUM.Add(result);
} else {
NUM.Add(result);
}
return;
}
// 3. 其他的 都进行比较 高的进入,低的取出计算再入栈,然后再比较直至运算级高再进栈
else {
// 这里又分成几种情况:
// 栈顶是+-,有可能直接进栈(*/时)
// 其他情况都不行
// 增加一个运算符优先级判断的函数,因为要进行循环的一个比较
while (!SIGN.IsEmpty() && !GAO(ch, SIGN.GetTop())) // 运算级低的时候 //////////////加一个判断为空
{
string yunsuanfu = SIGN.Delete();
string num2 = NUM.Delete();
string num1 = NUM.Delete();
string result = OPER(num1, yunsuanfu, num2);
if (result == "") {
// cout << "出现负数!" << endl;
fushuchuxian++;
return;
}
if (result == "!") {
// cout << "除数为0" << endl;
chushu0++;
return;
}
NUM.Add(result);
}
SIGN.Add(singleCharString);
return;
}
}
// 优化函数
string Optimize1(string to_str) {
// 移除表达式中的所有空格以简化后续正则操作
regex spaceRegex("\\s+");
to_str = regex_replace(to_str, spaceRegex, "");
// x - x = 0
regex pattern = regex("(\\w+)-(\\1)");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "0");
}
// x*0 or 0*x = 0
pattern = regex("(\\b[\\w]*\\*0\\b|\\b0\\*[\\w]*\\b)");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "0");
}
// 0/数字 = 0
pattern = regex("(0\\/([0-9]\\d*|0[0-9]\\d*))");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "0");
}
// 移除 +0, 0+, -0
pattern = regex("(\\+0|0\\+|\\-0)");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "");
}
// 移除 0-x
pattern = regex("(0\\-)");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "-");
}
// 移除 *1 和 1*
pattern = regex("(\\b1\\*|\\*1\\b)");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "");
}
// 移除 /1
pattern = regex("(\\/1\\b)");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "");
}
// 处理 -(-x) = x
pattern = regex("--([\\w]*)");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "$1");
}
// 去除单一对括号 ((a)) -> (a)
pattern = regex(R"(\(([a-zA-Z]|\d+)\))");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "$1");
}
// 去除括号中仅包含乘法运算的表达式
pattern = regex(R"(\(((?:[0-9a-zA-Z]+\*)+[0-9a-zA-Z]+)\))");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "$1");
}
pattern = regex(R"(\(([^()]+)\))");
if (regex_search(to_str, smatch(), pattern)) {
return regex_replace(to_str, pattern, "$1");
}
return to_str; // 如果没有匹配到任何模式,则返回原始字符串
}
int main() {
LinkedStack NUM;
LinkedStack SIGN;
string inputLine;
while (true) {
cout << "请输入表达式(字符间不要有空格), 输入'exit'结束: ";
getline(cin, inputLine);
if (inputLine == "exit") break;
// 合法性检查
if (!valid(inputLine)) {
cout << "False" << endl;
continue;
} else {
cout << "True" << endl;
}
inputLine += " "; // 方便处理最后一个字符
string number = "";
int fushuchuxian = 0;
int chushu0 = 0;
// 遍历输入的字符串
for (char ch : inputLine) {
string singleCharString(1, ch);
if (isdigit(ch))
number += ch;
else {
if (!number.empty()) {
NUM.Add(number);
number = "";
}
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
NUM.Add(singleCharString);
}
if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')') {
SIGNADD(NUM, SIGN, singleCharString, ch, fushuchuxian, chushu0);
if (fushuchuxian == 1) {
cout << "出现负数!" << endl;
break;
}
if (chushu0 == 1) {
cout << "除数为0或存在字母!" << endl;
break;
}
}
}
}
if (fushuchuxian == 1 || chushu0 == 1) continue;
// 处理所有运算
while (!SIGN.IsEmpty()) {
string yunsuanfu = SIGN.Delete();
string num2 = NUM.Delete();
string num1 = NUM.Delete();
string result = OPER(num1, yunsuanfu, num2);
if (result == "" || result == "!") {
cout << "除数为0或字母或出现负数" << endl;
break;
}
NUM.Add(result);
}
if (!SIGN.IsEmpty()) continue;
string result = NUM.GetTop();
cout << result << endl;
for (int i = 0; i < 10; i++) {
result = Optimize1(result);
cout << result << endl;
}
cout << "最终结果: " << result << endl;
}
return 0;
}
```
### 修改说明
1. **增加了合并同类项的功能**:在 `main` 函数中调用 `Optimize1` 函数多次,以确保表达式尽可能简化。
2. **优化了 `Optimize1` 函数**:通过正则表达式处理各种优化情况,例如 `x - x = 0`、`x * 0 = 0` 等。
3. **保持原有结构不变**:所有的修改都在现有的框架内进行,未改变其他地方的代码结构。
4. **增加了必要的注释**:在修改的地方添加了注释,以便理解修改的目的和方法。
阅读全文