再探利用C++的STL和堆栈编程思想实现数学四则运算计算结果
此次修改了上次的版本,利用了堆栈的编程思想,实现了支持括号的四则运算
跟上个版本一样,吧表达式存储到a.txt中:
结果保存在b.txt中:
堆栈编程思路:
1. 建立两个堆,一个字符堆,用于存储+、-、*、/、%、=;一个数字堆,用于存储数字
2. 创建两个字符,一个存储堆顶的操作符,一个存储表达式中的操作符
3. 建立一个二维表,利用2.中的两个操作符转化为行和列,在二维表中找到对应的判断
4. 若是小于,则表示,表达式中的操作符优先级比原先的操作符优先级高,直接压入堆中存储
5. 若是大于,则表示堆顶的操作符优先级高,所以先计算,把数字堆中的两个数弹出,计算结果,压回堆中存储,并把表达式中的操作符压入字符堆中
6. 若为0,则表示表达式不合法
7. 若为=,则有两种情况,一个是表达式计算完成,把结果存储到answer中。另外一种是括号配对了,需要把前括号pop了
以上是主思路,次思路跟上次一样:
1. 打开a.txt;
2. 利用getline吧每行的表达式读出来,存入string类对象中;
3. 循环读取,循环计算结果;
4. 循环完成,把answer中的结果存储到b.txt;
差不多就这样,下面附上代码:
1 // Arithmetic3.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <iostream> 6 #include <fstream> 7 #include <string> 8 #include <vector> 9 #include <deque> 10 #include <stack> 11 #include <stdio.h> 12 13 using namespace std; 14 15 //+ - * / % ( ) = 16 char ss[8][8] ={{'>','>','<','<','<','<','>','>'}, 17 {'>','>','<','<','<','<','>','>'}, 18 {'>','>','>','>','>','<','>','>'}, 19 {'>','>','>','>','>','<','>','>'}, 20 {'>','>','>','>','>','<','>','>'}, 21 {'<','<','<','<','<','<','=','0'}, 22 {'>','>','>','>','>','0','>','>'}, 23 {'<','<','<','<','<','<','0','='}}; 24 //大于号,弹出数字,进行计算,小于号,压入堆栈中 25 26 //把字符转化成相应的行和列 27 void getRowCol (const char stackCh, const char ch, int& row, int& col) 28 { 29 switch (stackCh) 30 { 31 case '+': 32 row = 0; 33 break; 34 case '-': 35 row = 1; 36 break; 37 case '*': 38 row = 2; 39 break; 40 case '/': 41 row = 3; 42 break; 43 case '%': 44 row = 4; 45 break; 46 case '(': 47 row = 5; 48 break; 49 case ')': 50 row = 6; 51 break; 52 case '=': 53 row = 7; 54 break; 55 } 56 switch (ch) 57 { 58 case '+': 59 col = 0; 60 break; 61 case '-': 62 col = 1; 63 break; 64 case '*': 65 col = 2; 66 break; 67 case '/': 68 col = 3; 69 break; 70 case '%': 71 col = 4; 72 break; 73 case '(': 74 col = 5; 75 break; 76 case ')': 77 col = 6; 78 break; 79 case '=': 80 col = 7; 81 break; 82 } 83 84 } 85 86 //写入文件 87 void writeAnswer(vector<int>& iAnswer) 88 { 89 ofstream ofs("b.txt"); 90 for(vector<int>::size_type ix = 0; ix != iAnswer.size(); ix++) 91 { 92 ofs << iAnswer[ix] << '\n'; 93 } 94 ofs.close(); 95 } 96 97 98 void countAnswer(vector<int>& iAnswer, string& str) 99 { 100 int temp = 0; 101 int row = 0 ,col = 0; 102 stack<int> iStk; //定义数据堆 103 stack<char> cStk; //定义字符堆 104 char stackCh = '\0'; 105 char ch = '\0'; 106 cStk.push('='); //先把=压入字符堆中,以备匹配等号 107 for (string::size_type ix = 0; ix != str.size(); ix++) 108 { 109 //如果是数字,先判断下一个字符是否也是数字,如果不是,就压入数据堆中 110 if (str[ix] >= '0' && str[ix] <= '9') 111 { 112 temp = str[ix] - '0' + temp * 10; 113 if (str[ix + 1] < '0' || str[ix + 1] > '9') 114 { 115 iStk.push(temp); 116 } 117 } 118 else 119 { 120 /* iStk.push(temp);*/ 121 temp = 0; 122 stackCh = cStk.top(); //弹出字符堆的堆顶字符 123 ch = str[ix]; //读取字符串中的字符 124 if (ch == '=' || ch == ')') //遇到 = 号,或者),先执行判断 125 { 126 ix--; 127 } 128 getRowCol(stackCh,ch,row,col); ////把字符转化成相应的行和列 129 switch(ss[row][col]) 130 { 131 case '=': //遇到括号匹配,或者=号匹配,计算结束 132 if ( ch == '=') 133 { 134 iAnswer.push_back(iStk.top()); 135 return ; 136 } 137 else 138 { 139 cStk.pop(); 140 ix++; 141 } 142 143 break; 144 case '>': //取出堆中的两个数据,执行计算 145 { 146 int num2 = iStk.top(); 147 iStk.pop(); 148 int num1 = iStk.top(); 149 iStk.pop(); 150 stackCh = cStk.top(); 151 cStk.pop(); 152 if (ch != '=' && ch != ')') 153 { 154 cStk.push(ch); 155 } 156 switch(stackCh) 157 { 158 case '+': 159 num1 += num2; 160 break; 161 case '-': 162 num1 -= num2; 163 break; 164 case '*': 165 num1 *= num2; 166 break; 167 case '/': 168 num1 /= num2; 169 break; 170 case '%': 171 num1 %= num2; 172 break; 173 } 174 iStk.push(num1); 175 break; 176 } 177 case '<': //压入堆中 178 cStk.push(ch); 179 break; 180 case '0': //表达式错误 181 cout << "error arithmetic" << endl; 182 return ; 183 } 184 } 185 } 186 } 187 188 189 void countMath() 190 { 191 ifstream ifs("a.txt"); 192 if (!ifs.is_open()) 193 { 194 ifs.clear(); 195 fstream fs("a.txt",ios_base::out); //如果打开失败就创建文件a.txt 196 fs.close(); 197 ifs.open("a.txt"); 198 } 199 string temp; 200 deque<string> sDeq; 201 while (!ifs.eof()) 202 { 203 getline(ifs,temp); //按行读取数据,存储到双端队列中 204 sDeq.push_back(temp); 205 } 206 207 ifs.close(); 208 209 vector<int> iAnswer; 210 for (deque<string>::size_type ix = 0; ix != sDeq.size(); ix++) 211 { 212 string str; 213 str = sDeq.front(); 214 sDeq.pop_front(); 215 ix--; 216 //计算每一行的表达式 217 countAnswer(iAnswer,str); 218 } 219 220 writeAnswer(iAnswer); 221 } 222 223 int _tmain(int argc, _TCHAR* argv[]) 224 { 225 countMath(); 226 return 0; 227 }
posted on 2014-04-04 14:43 Sam.Richard 阅读(1888) 评论(1) 编辑 收藏 举报