生活随笔
收集整理的這篇文章主要介紹了
数据结构课程设计:算术表达式的求值
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、課程設計題目及內容
[問題描述]
一個算術表達式是由操作數(operand)、運算符(operator)和界限符(delimiter)組成的。假設操作數是正實數,運算符只含加減乘除等四種運算符,界限符有左右括號和表達式起始、結束符“#”,如:#(7+15)*(23-28/4)#。引入表達式起始、結束符是為了方便。編程利用“運算符優先法”求算術表達式的值。
[基本要求]
(1) 從鍵盤或文件讀入一個合法的算術表達式,輸出正確的結果。
(2) 顯示輸入序列和棧的變化過程。
(3) 考慮算法的健壯性,當表達式錯誤時,要給出錯誤原因的提示。
二、程序中使用的數據結構及主要符號說明
程序中使用了堆棧,其中OPTR為運算符棧(運算符包括‘+’‘-’‘*’‘/’‘(’‘)’‘[’‘]’’{’’}’’#’),OPND為操作數棧(操作數包括‘0’’1’’2’’3’’4’‘5’‘6’‘7’‘8’‘9’)
三、程序流程圖和帶有注釋的源程序
源代碼:
#include<iostream>
using namespace std
;
typedef struct SNode1
{char data
;struct SNode1
* next
;
}StackNode1
, * Linkstack1
;
typedef struct SNode2
{int data
;struct SNode2
* next
;
}StackNode2
, * Linkstack2
;
void InitStack1(Linkstack1
& S
)
{S
= NULL;
}
void InitStack2(Linkstack2
& S
)
{S
= NULL;
}
void push1(Linkstack1
& S
, char ch
)
{Linkstack1 p
;p
= (Linkstack1
)malloc(sizeof(Linkstack1
));p
->data
= ch
;p
->next
= S
;S
= p
;
}
void push2(Linkstack2
& S
, int ch
)
{Linkstack2 p
;p
= (Linkstack2
)malloc(sizeof(Linkstack2
));p
->data
= ch
;p
->next
= S
;S
= p
;
}
char GetTop1(Linkstack1
& S
)
{if (S
!= NULL)return S
->data
;
}
int GetTop2(Linkstack2
& S
)
{if (S
!= NULL)return S
->data
;
}
void pop1(Linkstack1
& S
, char& e
)
{ e
= GetTop1(S
);if (S
!= NULL){S
= S
->next
;}
}
void pop2(Linkstack2
& S
, int& e
)
{ if (S
!= NULL){e
= GetTop2(S
);S
= S
->next
;}
}
int In(char ch
)
{ switch (ch
){case '(':return 1;case ')':return 1;case '+':return 1;case '-':return 1;case '*':return 1;case '/':return 1;case '#':return 1;case '[':return 1;case ']':return 1;case '{':return 1;case '}':return 1;default: return 0;}
}
char Precede(char a
, char b
)
{if (b
== '+'){if (a
== '(' || a
== '#' || a
== '[' || a
== '{') return '<';return '>';}if (b
== '-'){if (a
== '(' || a
== '#' || a
== '[' || a
== '{') return '<';return '>';}if (b
== '*'){if (a
== '*' || a
== '/' || a
== ')' || a
== ']' || a
== '}') return '>';return '<';}if (b
== '/'){if (a
== '*' || a
== '/' || a
== ')' || a
== ']' || a
== '}') return '>';return '<';}if (b
== '(') return '<';if (b
== ')'){if (a
== '(') return '=';return '>';}if (b
== '#'){if (a
== '#') return '=';return '>';}if (b
== '['){if (a
== ')') return '>';return '<';}if (b
== ']'){if (a
== '[') return '=';return '>';}if (b
== '{'){if (a
== ')' || a
== ']') return '>';return '<';}if (b
== '}'){if (a
== '{') return '=';return '>';}
}
int Operate(int a
, char op
, int b
)
{switch (op
){case '+':return a
+ b
; break;case '-':return a
- b
; break;case '*':return a
* b
; break;case '/':return a
/ b
; break;}
}
void Cout_stack1(Linkstack1
& S
)
{Linkstack1 T
;T
= new StackNode1
;T
= S
;if (T
== NULL){cout
<< "運算符棧為空!!";}while (T
){cout
<< T
->data
<< '\t';T
= T
->next
;}cout
<< endl
;
}void Cout_stack2(Linkstack2
& S
)
{Linkstack2 T
;T
= new StackNode2
;T
= S
;if (T
== NULL){cout
<< "操作數棧為空!!";}while (T
){cout
<< T
->data
<< '\t';T
= T
->next
;}cout
<< endl
;
}
int EvaluateExpression()
{char theta
= 0, x
= 0;int a
= 0, b
= 0;Linkstack1 OPTR
;Linkstack2 OPND
;Linkstack1 q
;InitStack1(OPTR
);InitStack2(OPND
);InitStack1(q
);cout
<< "請輸入算術表達式:";push1(OPTR
, '#');char ch
;cin
>> ch
;cout
<< "----------------------------------------" << endl
;if (ch
== ')' ||ch
==']'||ch
=='}'|| ch
== '+' || ch
== '-' || ch
== '*' || ch
== '/'){cout
<< "輸入錯誤!!!表達式第一個值不能為運算符" << endl
;cout
<< "----------------------------------------" << endl
;cout
<< endl
;cin
.ignore(100, '\n');return 77777;}cout
<< "初始運算符棧:";Cout_stack1(OPTR
);cout
<< "初始操作數棧:";Cout_stack2(OPND
);cout
<< "----------------------------------------" << endl
;while (ch
!= '#' || GetTop1(OPTR
) != '#'){cout
<< "輸入序列:" << ch
<< endl
;q
= OPTR
;if (ch
!= '#' && ch
!= '0' && ch
!= '1' && ch
!= '2' && ch
!= '3' && ch
!= '4' && ch
!= '5' && ch
!= '6' && ch
!= '7' && ch
!= '8' && ch
!= '9' && ch
!= '+' && ch
!= '-' && ch
!= '*' && ch
!= '/' && ch
!= '(' && ch
!= ')' && ch
!= '[' && ch
!= ']' && ch
!= '{' && ch
!= '}'){cout
<< "錯誤!!!非法輸入!!!!" << endl
;cout
<< "----------------------------------------" << endl
;cout
<< endl
;cin
.ignore(100, '\n');return 77777;}if (ch
== ')'){while (q
->data
!= '(' && q
->next
){q
= q
->next
;}if (q
->data
!= '('){cout
<< "錯誤!!!右小括號輸入過多!!!" << endl
;cout
<< "----------------------------------------" << endl
;cout
<< endl
;cin
.ignore(100, '\n');return 77777;}}if (ch
== ']'){while (q
->data
!= '[' && q
->next
){q
= q
->next
;}if (q
->data
!= '['){cout
<< "錯誤!!!右中括號輸入過多!!!" << endl
;cout
<< "----------------------------------------" << endl
;cout
<< endl
;cin
.ignore(100, '\n');return 77777;}}if (ch
== '}'){while (q
->data
!= '{' && q
->next
){q
= q
->next
;}if (q
->data
!= '{'){cout
<< "錯誤!!!右大括號輸入過多!!!" << endl
;cout
<< "----------------------------------------" << endl
;cout
<< endl
;cin
.ignore(100, '\n');return 77777;}}if (!In(ch
)){ int q
= 0;q
= ch
- 48;int temp
, temp1
;push2(OPND
, q
);cin
>> ch
;cout
<< "輸入序列:" << ch
<< endl
;for (int i
= 0; i
< 99; i
++){if (ch
>= 48 && ch
<= 57){int l
= ch
- 48;pop2(OPND
, temp
);temp1
= temp
* 10 + l
;push2(OPND
, temp1
);cin
>> ch
;cout
<< "輸入序列:" << ch
<< endl
;}}}else{switch (Precede(GetTop1(OPTR
), ch
)){case'<':push1(OPTR
, ch
); cin
>> ch
; break;case'>':pop1(OPTR
, theta
); pop2(OPND
, b
);if (OPND
== NULL){cout
<< "錯誤!!!運算符過多!!!" << endl
;cout
<< "----------------------------------------" << endl
;cout
<< endl
;cin
.ignore(100, '\n');return 77777;}pop2(OPND
, a
);push2(OPND
, Operate(a
, theta
, b
)); break;case'=':pop1(OPTR
, x
); cin
>> ch
; break;}}if (ch
== '#'){if (q
->data
== '('){q
= q
->next
;if (q
->data
== '('){cout
<< "錯誤!!!左小括號輸入過多!!!" << endl
;cout
<< "----------------------------------------" << endl
;cout
<< endl
;cin
.ignore(100, '\n');return 77777;}}}if (ch
== '#'){if (q
->data
== '['){q
= q
->next
;if (q
->data
== '['){cout
<< "錯誤!!!左中括號輸入過多!!!" << endl
;cout
<< "----------------------------------------" << endl
;cout
<< endl
;cin
.ignore(100, '\n');return 77777;}}}if (ch
== '#'){if (q
->data
== '{'){q
= q
->next
;if (q
->data
== '{'){cout
<< "錯誤!!!左大括號輸入過多!!!" << endl
;cout
<< "----------------------------------------" << endl
;cout
<< endl
;cin
.ignore(100, '\n');return 77777;}}}cout
<< "運算符棧:";Cout_stack1(OPTR
);cout
<< "操作數棧:";Cout_stack2(OPND
);cout
<< "----------------------------------------" << endl
;}cout
<< "運算符棧:";Cout_stack1(OPTR
);cout
<< "操作數棧:";Cout_stack2(OPND
);cout
<< "----------------------------------------" << endl
;return GetTop2(OPND
);
}
int main()
{for (int i
= 0; i
< 40; i
++){cout
<< "歡迎使用算術表達式計算器!!" << endl
;cout
<< "注意:輸入結束時請用#符號結束,否則將使程序崩潰!!!!" << endl
;int a
= EvaluateExpression();if (a
!= 77777){cout
<< "運算結果為:" << a
<< endl
;cout
<< "----------------------------------------" << endl
;cout
<< endl
;}}
}
四、執行程序,并打印程序運行時的初值和運算結果
輸入120/{240/[120/(1+1)]}#,程序將進行運算,打印出輸入序列,運算符棧和操作數棧里的內容,最后輸出運算結果為30
五、實驗結果分析,實驗收獲和體會
考慮到算法的健壯性,考慮各種錯誤輸入時,算法進行判斷,并給出錯誤原因
1、非法輸入時,如abcd或!&,系統會自動進行判斷
2、括號不匹配時,如左括號過多或者右括號過多,系統也會進行報錯,其中包括各種括號()[]{}
3、當輸入的運算符過多時,會導致操作數不夠用,系統會識別并且報錯
六、實驗的改進意見和建議
程序還需改進:
1、當用戶輸入算術表達式時,如果沒有輸入#,算法不會報錯,并且直接進行下去直到識別最后一個字符時才會停止,此時輸入#才能繼續進行算法.
建議:運用數組先存儲輸入進去的全部字符,掃描最后一個字符是否為#,若是#才能進行算法;若不是,系統報錯,停止算法。
2、算術表達式無法輸入負數.
建議:增加對于‘-’(ch=45)的判別函數
3、對于浮點數的運算沒有實現.
建議:增加對于‘.’(ch=46)的判別函數
總結
以上是生活随笔為你收集整理的数据结构课程设计:算术表达式的求值的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。