但為保持原汁原味,至今未做改進,供大家參考
主要的兩個小技巧:
1是對e的處理
2是對負號的處理
開發環境:VC++ 7.0
Calculator.h : 頭文件
1
// Calculator.h : 頭文件
2
//
3
#ifndef CALCULATOR_H_2005_04_27__
4
#define CALCULATOR_H_2005_04_27__
5
6
7
#include <stack>
8
9
using namespace std;
10
11
typedef stack<double> STACK_DOUBLE;
12
typedef stack<char> STACK_CHAR;
13
14
15
class CCalculator
16

{
17
public :
18
double CountResult(CString csExp);
19
int CheckString(CString csExp);
20
int ReturnError(CString csExp);
21
CCalculator(void);
22
23
private:
24
STACK_DOUBLE m_doubleStack; //操作數棧
25
STACK_CHAR m_charStack; //操作符號棧
26
static char m_priTable[8][8]; //運算符優先級列表
27
28
char QueryPri(char chOperator1,char chOperator2);
29
//查找運算符優先級
30
31
//int JudgeOperator(char ch);
32
// //判斷是否為操作符號
33
34
int JudgeOperator(CString csExp, int iLocation);
35
//判斷是否為操作符號
36
37
double Count(double dbNum1,double dbNum2, char chOper);
38
//四則運算函數,返回計算結果
39
40
double GetCurrentDouble(CString csExpression,int& iCurrentLocation);
41
//從表達式的當前位置查找操作數并返回,當前位置向前移動
42
43
44
};
45
46
47
#endif
48
49
// Calculator.h : 頭文件 2
// 3
#ifndef CALCULATOR_H_2005_04_27__ 4
#define CALCULATOR_H_2005_04_27__ 5

6

7
#include <stack> 8

9
using namespace std;10

11
typedef stack<double> STACK_DOUBLE; 12
typedef stack<char> STACK_CHAR; 13

14

15
class CCalculator 16


{ 17
public : 18
double CountResult(CString csExp); 19
int CheckString(CString csExp); 20
int ReturnError(CString csExp); 21
CCalculator(void); 22

23
private: 24
STACK_DOUBLE m_doubleStack; //操作數棧 25
STACK_CHAR m_charStack; //操作符號棧 26
static char m_priTable[8][8]; //運算符優先級列表 27

28
char QueryPri(char chOperator1,char chOperator2); 29
//查找運算符優先級 30

31
//int JudgeOperator(char ch); 32
// //判斷是否為操作符號 33

34
int JudgeOperator(CString csExp, int iLocation); 35
//判斷是否為操作符號 36

37
double Count(double dbNum1,double dbNum2, char chOper); 38
//四則運算函數,返回計算結果 39

40
double GetCurrentDouble(CString csExpression,int& iCurrentLocation); 41
//從表達式的當前位置查找操作數并返回,當前位置向前移動 42

43
44
}; 45

46

47
#endif 48

49

Calculator.cpp
1
//Calculator.cpp
2
3
4
#include "stdafx.h"
5
#include "Calculator.h"
6
#include <stack>
7
#include <math.h>
8
9
using namespace std;
10
11
12
//檢查表達式是否合法
13
int CCalculator::CheckString(CString csExp )
14

{
15
16
return 1;
17
18
};
19
20
//計算合法表達式的值
21
double CCalculator::CountResult(CString csExp)
22

{
23
int i = 0;
24
int j = 0;
25
int iLength = 0;
26
int& alia_i = i;
27
char chMyOperator = '\0';
28
char chCompareResult = '\0';
29
char chCurrent = '\0';
30
char chTop = '\0';
31
double dbNumber1 = 0.0;
32
double dbNumber2 = 0.0;
33
double dbResult = 0.0;
34
double dbCurrentNumber = 0.0;
35
36
csExp += "#";
37
iLength = csExp.GetLength(); //獲取表達式的長度
38
m_charStack.push('#');
39
40
for (i=0; i<=iLength; )
41
{
42
chCurrent = csExp[i];
43
44
if ( JudgeOperator(csExp,i) ) //如果為操作符
45
{
46
//比較當前操作符與棧頂操作符的優先級
47
chTop = m_charStack.top();
48
chCompareResult = QueryPri(chCurrent, chTop);
49
50
51
switch (chCompareResult)
52
//根據比較結果執行不同的操作
53
{
54
case '>' :
55
//當前操作符優先級較高,壓入操作符號棧
56
m_charStack.push(chCurrent);
57
i++;
58
break;
59
60
case '<' :
61
//當前操作符優先級較小,計算前面的運算結果
62
chMyOperator = m_charStack.top();
63
m_charStack.pop();
64
dbNumber2 = m_doubleStack.top();
65
m_doubleStack.pop();
66
dbNumber1 = m_doubleStack.top();
67
m_doubleStack.pop();
68
dbResult = Count(dbNumber1, dbNumber2, chMyOperator);
69
m_doubleStack.push(dbResult);
70
break;
71
72
case '=' :
73
//當前操作符與棧頂操作符優先級相同,有兩種可能
74
75
if (chCurrent==')')
76
//如果為左右括號相遇,脫括號
77
{
78
m_charStack.pop();
79
i++;
80
break;
81
}//end if
82
else
83
//如果為兩個'#'相遇,運算結束
84
{
85
if (chCurrent=='#')
86
{
87
dbResult = m_doubleStack.top();
88
return dbResult;
89
break;
90
}//end if
91
92
}//end else
93
94
case 'E' :
95
//比較出錯
96
break;
97
98
default:
99
break;
100
101
}//end switch
102
103
104
}//end if
105
else
106
{
107
dbCurrentNumber = GetCurrentDouble(csExp,alia_i);
108
m_doubleStack.push(dbCurrentNumber);
109
110
}//end else
111
112
}//end for
113
114
115
return dbResult;
116
117
118
119
};
120
121
122
//對不合法的表達式,找到錯誤,通知用戶修改
123
int CCalculator::ReturnError(CString csExp)
124

{
125
return 1;
126
127
};
128
129
//查找運算符優先級
130
char CCalculator::QueryPri (char chOperator1, char chOperator2)
131

{
132
int i = 0;
133
int j = 0;
134
135
switch (chOperator1)
136
{
137
case '+':
138
i = 0;
139
break;
140
case '-':
141
i = 1;
142
break;
143
case '*':
144
i = 2;
145
break;
146
case '/':
147
i = 3;
148
break;
149
case '(':
150
i = 4;
151
break;
152
case ')':
153
i = 5;
154
break;
155
case '#':
156
i = 6;
157
break;
158
case 'e':
159
i = 7;
160
break;
161
default:
162
break;
163
};
164
165
switch (chOperator2)
166
{
167
case '+':
168
j = 0;
169
break;
170
case '-':
171
j = 1;
172
break;
173
case '*':
174
j = 2;
175
break;
176
case '/':
177
j = 3;
178
break;
179
case '(':
180
j = 4;
181
break;
182
case ')':
183
j = 5;
184
break;
185
case '#':
186
j = 6;
187
break;
188
case 'e':
189
j = 7;
190
break;
191
default:
192
break;
193
};
194
195
return m_priTable[i][j];
196
};
197
198
//初始化運算符優先級列表
199
char CCalculator::m_priTable[8][8] =
200

{
201
//+,,,-,,,*,,,/,,,(,,,),,,#,,,e,
202
{'<','<','<','<','>','E','>','<'}, //+
203
{'<','<','<','<','>','E','>','<'}, //-
204
{'>','>','<','<','>','E','>','<'}, //*
205
{'>','>','<','<','>','E','>','<'}, /**////
206
{'>','>','>','>','>','E','>','E'}, //(
207
{'<','<','<','<','=','E','E','<'}, //)
208
{'<','<','<','<','<','<','=','<'}, //#
209
{'>','>','>','>','>','E','>','E'} //e
210
211
212
213
};
214
215
//構造函數
216
CCalculator::CCalculator(void)
217

{
218
int i = 0;
219
220
stack<double>::size_type double_Length;
221
stack<char>::size_type char_Length;
222
223
224
if (!(m_doubleStack.empty()))
225
//初始化操作數棧
226
{
227
double_Length = m_doubleStack.size();
228
229
for (i=1; i<=double_Length; i++)
230
{
231
m_doubleStack.pop();
232
}//end for
233
}//end if
234
235
236
if (!(m_charStack.empty()))
237
//初始化操作符號棧
238
{
239
char_Length=m_charStack.size();
240
241
for ( i=1; i<=char_Length; i++)
242
{
243
m_charStack.pop();
244
}//end for
245
246
}//end if
247
248
};
249
250
251
252
//判斷是否為運算符
253
int CCalculator::JudgeOperator(CString csExp, int iLocation)
254

{
255
switch (csExp[iLocation])
256
{
257
case '+':
258
return 1;
259
break;
260
case '-':
261
if (iLocation==0)
262
{
263
return 0;
264
break;
265
}
266
else
267
{ if ((csExp[iLocation-1]=='(') || (csExp[iLocation-1]=='e'))
268
{
269
return 0;
270
break;
271
}
272
else
273
{
274
return 1;
275
break;
276
}
277
}
278
return 1;
279
break;
280
case '*':
281
return 1;
282
break;
283
case '/':
284
return 1;
285
break;
286
case '(':
287
return 1;
288
break;
289
case ')':
290
return 1;
291
break;
292
case '#':
293
return 1;
294
break;
295
case 'e':
296
return 1;
297
break;
298
default :
299
return 0;
300
break;
301
302
};
303
};
304
305
//四則運算函數,返回結果
306
double CCalculator::Count(double dbNum1, double dbNum2, char chOper)
307

{
308
double dbResult = 0.0;
309
310
switch (chOper)
311
{
312
case '+':
313
dbResult = dbNum1 + dbNum2;
314
break;
315
316
case '-':
317
dbResult = dbNum1 - dbNum2;
318
break;
319
320
case '*':
321
dbResult = dbNum1 * dbNum2;
322
break;
323
324
case '/':
325
if (!(fabs(dbNum2 - 0.0) < 1e-6 ))
326
{
327
dbResult = dbNum1 / dbNum2;
328
329
}
330
break;
331
332
case 'e':
333
dbResult = dbNum1 * pow(10.0,dbNum2);
334
break;
335
336
default:
337
break;
338
};
339
340
return dbResult;
341
342
};
343
344
//從表達式的當前位置查找操作數并返回,當前位置向前移動
345
double CCalculator::GetCurrentDouble(CString csExpression,int& iCurrentLocation)
346

{
347
int i = 0;
348
int j = 0;
349
int iExpressionLength = 0;
350
int iELocation = 0;
351
CString csDoubleString("");
352
char chCurrentChar = '\0';
353
double dbNumber = 0.0;
354
i = iCurrentLocation;
355
356
iExpressionLength = csExpression.GetLength();
357
358
for ( j=i+1; j<iExpressionLength; )
359
{
360
chCurrentChar = csExpression[j];
361
362
if (!JudgeOperator(csExpression,j))
363
{
364
j++;
365
366
}//end if
367
else
368
{
369
370
break;
371
372
373
}//end else
374
375
}//end for
376
377
csDoubleString = csExpression.Mid(i, j-i);
378
379
dbNumber = atof(csDoubleString);
380
381
382
383
iCurrentLocation = j;
384
385
return dbNumber;
386
387
388
};
389
390
//Calculator.cpp 2

3

4
#include "stdafx.h" 5
#include "Calculator.h" 6
#include <stack> 7
#include <math.h> 8

9
using namespace std;10

11

12
//檢查表達式是否合法 13
int CCalculator::CheckString(CString csExp ) 14


{ 15
16
return 1; 17
18
}; 19

20
//計算合法表達式的值 21
double CCalculator::CountResult(CString csExp) 22


{ 23
int i = 0; 24
int j = 0; 25
int iLength = 0; 26
int& alia_i = i; 27
char chMyOperator = '\0'; 28
char chCompareResult = '\0'; 29
char chCurrent = '\0'; 30
char chTop = '\0'; 31
double dbNumber1 = 0.0; 32
double dbNumber2 = 0.0; 33
double dbResult = 0.0; 34
double dbCurrentNumber = 0.0; 35
36
csExp += "#"; 37
iLength = csExp.GetLength(); //獲取表達式的長度 38
m_charStack.push('#'); 39

40
for (i=0; i<=iLength; ) 41

{ 42
chCurrent = csExp[i]; 43

44
if ( JudgeOperator(csExp,i) ) //如果為操作符 45

{ 46
//比較當前操作符與棧頂操作符的優先級 47
chTop = m_charStack.top(); 48
chCompareResult = QueryPri(chCurrent, chTop); 49
50

51
switch (chCompareResult) 52
//根據比較結果執行不同的操作 53

{ 54
case '>' : 55
//當前操作符優先級較高,壓入操作符號棧 56
m_charStack.push(chCurrent); 57
i++; 58
break; 59

60
case '<' : 61
//當前操作符優先級較小,計算前面的運算結果 62
chMyOperator = m_charStack.top(); 63
m_charStack.pop(); 64
dbNumber2 = m_doubleStack.top(); 65
m_doubleStack.pop(); 66
dbNumber1 = m_doubleStack.top(); 67
m_doubleStack.pop(); 68
dbResult = Count(dbNumber1, dbNumber2, chMyOperator); 69
m_doubleStack.push(dbResult); 70
break; 71

72
case '=' : 73
//當前操作符與棧頂操作符優先級相同,有兩種可能 74
75
if (chCurrent==')') 76
//如果為左右括號相遇,脫括號 77

{ 78
m_charStack.pop(); 79
i++; 80
break; 81
}//end if 82
else 83
//如果為兩個'#'相遇,運算結束 84

{ 85
if (chCurrent=='#') 86

{ 87
dbResult = m_doubleStack.top(); 88
return dbResult; 89
break; 90
}//end if 91

92
}//end else 93
94
case 'E' : 95
//比較出錯 96
break; 97
98
default: 99
break; 100

101
}//end switch 102
103
104
}//end if 105
else 106

{ 107
dbCurrentNumber = GetCurrentDouble(csExp,alia_i); 108
m_doubleStack.push(dbCurrentNumber); 109

110
}//end else 111
112
}//end for 113

114

115
return dbResult; 116
117
118

119
};120

121

122
//對不合法的表達式,找到錯誤,通知用戶修改 123
int CCalculator::ReturnError(CString csExp) 124


{ 125
return 1; 126

127
};128

129
//查找運算符優先級 130
char CCalculator::QueryPri (char chOperator1, char chOperator2) 131


{ 132
int i = 0; 133
int j = 0; 134

135
switch (chOperator1) 136

{ 137
case '+': 138
i = 0; 139
break; 140
case '-': 141
i = 1; 142
break; 143
case '*': 144
i = 2; 145
break; 146
case '/': 147
i = 3; 148
break; 149
case '(': 150
i = 4; 151
break; 152
case ')': 153
i = 5; 154
break; 155
case '#': 156
i = 6; 157
break; 158
case 'e': 159
i = 7; 160
break; 161
default: 162
break; 163
}; 164

165
switch (chOperator2) 166

{ 167
case '+': 168
j = 0; 169
break; 170
case '-': 171
j = 1; 172
break; 173
case '*': 174
j = 2; 175
break; 176
case '/': 177
j = 3; 178
break; 179
case '(': 180
j = 4; 181
break; 182
case ')': 183
j = 5; 184
break; 185
case '#': 186
j = 6; 187
break; 188
case 'e': 189
j = 7; 190
break; 191
default: 192
break; 193
}; 194

195
return m_priTable[i][j]; 196
}; 197

198
//初始化運算符優先級列表 199
char CCalculator::m_priTable[8][8] = 200


{ 201
//+,,,-,,,*,,,/,,,(,,,),,,#,,,e, 202

{'<','<','<','<','>','E','>','<'}, //+ 203

{'<','<','<','<','>','E','>','<'}, //- 204

{'>','>','<','<','>','E','>','<'}, //* 205

{'>','>','<','<','>','E','>','<'}, /**//// 206

{'>','>','>','>','>','E','>','E'}, //( 207

{'<','<','<','<','=','E','E','<'}, //) 208

{'<','<','<','<','<','<','=','<'}, //# 209

{'>','>','>','>','>','E','>','E'} //e 210

211

212
213
}; 214

215
//構造函數 216
CCalculator::CCalculator(void) 217


{ 218
int i = 0; 219

220
stack<double>::size_type double_Length; 221
stack<char>::size_type char_Length; 222

223

224
if (!(m_doubleStack.empty())) 225
//初始化操作數棧 226

{ 227
double_Length = m_doubleStack.size(); 228

229
for (i=1; i<=double_Length; i++) 230

{ 231
m_doubleStack.pop(); 232
}//end for 233
}//end if 234

235
236
if (!(m_charStack.empty())) 237
//初始化操作符號棧 238

{ 239
char_Length=m_charStack.size(); 240

241
for ( i=1; i<=char_Length; i++) 242

{ 243
m_charStack.pop(); 244
}//end for 245
246
}//end if 247
248
}; 249

250

251

252
//判斷是否為運算符 253
int CCalculator::JudgeOperator(CString csExp, int iLocation) 254


{ 255
switch (csExp[iLocation]) 256

{ 257
case '+': 258
return 1; 259
break; 260
case '-': 261
if (iLocation==0) 262

{ 263
return 0; 264
break; 265
} 266
else 267

{ if ((csExp[iLocation-1]=='(') || (csExp[iLocation-1]=='e')) 268

{ 269
return 0; 270
break; 271
} 272
else 273

{ 274
return 1; 275
break; 276
} 277
} 278
return 1; 279
break; 280
case '*': 281
return 1; 282
break; 283
case '/': 284
return 1; 285
break; 286
case '(': 287
return 1; 288
break; 289
case ')': 290
return 1; 291
break; 292
case '#': 293
return 1; 294
break; 295
case 'e': 296
return 1; 297
break; 298
default : 299
return 0; 300
break; 301

302
}; 303
}; 304

305
//四則運算函數,返回結果 306
double CCalculator::Count(double dbNum1, double dbNum2, char chOper) 307


{ 308
double dbResult = 0.0; 309

310
switch (chOper) 311

{ 312
case '+': 313
dbResult = dbNum1 + dbNum2; 314
break; 315

316
case '-': 317
dbResult = dbNum1 - dbNum2; 318
break; 319

320
case '*': 321
dbResult = dbNum1 * dbNum2; 322
break; 323

324
case '/': 325
if (!(fabs(dbNum2 - 0.0) < 1e-6 )) 326

{ 327
dbResult = dbNum1 / dbNum2; 328

329
} 330
break; 331
332
case 'e': 333
dbResult = dbNum1 * pow(10.0,dbNum2); 334
break; 335

336
default: 337
break; 338
}; 339

340
return dbResult; 341
342
}; 343

344
//從表達式的當前位置查找操作數并返回,當前位置向前移動 345
double CCalculator::GetCurrentDouble(CString csExpression,int& iCurrentLocation) 346


{ 347
int i = 0; 348
int j = 0; 349
int iExpressionLength = 0; 350
int iELocation = 0; 351
CString csDoubleString(""); 352
char chCurrentChar = '\0'; 353
double dbNumber = 0.0; 354
i = iCurrentLocation; 355
356
iExpressionLength = csExpression.GetLength(); 357
358
for ( j=i+1; j<iExpressionLength; ) 359

{ 360
chCurrentChar = csExpression[j]; 361

362
if (!JudgeOperator(csExpression,j)) 363

{ 364
j++; 365

366
}//end if 367
else 368

{ 369
370
break; 371

372
373
}//end else 374
375
}//end for 376

377
csDoubleString = csExpression.Mid(i, j-i); 378
379
dbNumber = atof(csDoubleString); 380

381
382
383
iCurrentLocation = j; 384

385
return dbNumber;386

387

388
}; 389

390


