問題
缺陷
1.輸入必須正確輸入算符(運算符+界限符)和操作數,若輸入非(算符和操作數),無法判斷出(因爲默認非算符的數都爲操作數,否則無法保留兩位數及以上的運算結果)
2.輸入的操作數必須爲個位數,因爲輸入類型是字符,只能讀取一個字符(且,輸入類型不能是int型,int無法寫入算符)
3.運算結果只能返回255個值(ASCII碼只能表示255個:-128127其中0127纔有對照表)範圍:(-176+48=-128,再小就超出範圍)-1760(‘0’爲48)79(79+48=127,再大就超出範圍了),超出範圍(過小則變爲79逐漸變小;過大則變爲-176逐漸變大)
4.算符匹配錯誤返回-1
#include <stdio.h>
#include <stdlib.h>
#include<iostream>
#include<string>
using namespace std;
typedef enum {da , xiao, deng, ERROR }pre;//枚舉元素得是字母與數字組成的符號序列
typedef char ElemType;
typedef struct StackNode* StackLink;
struct StackNode{
ElemType data;
StackLink next;
};
//初始化
void InitStack(StackLink &S){
S = NULL;
return;
}
//入棧
void Push(StackLink &S, ElemType e){
StackLink p = (StackLink)malloc(sizeof(StackNode));
p->data = e;
p->next = S;
S = p;
return;
}
//出棧
void Pop(StackLink &S, ElemType &e){
e = S->data;
S = S->next;
return;
}
//返回棧頂元素
ElemType GetHead(StackLink S){
if (S == NULL)return 0;
return S->data;
}
//堆棧判空
bool StackEmpty(StackLink S){
if (S == NULL)return true;
return false;
}
//算符判斷優先級
pre Precede(ElemType x,ElemType y){
if ((x == '('&&y == '#') || (x == ')'&&y == '(') || (x == '#'&&y == ')'))
return ERROR;
else if (x == '+'||x=='-'){
if (y == '+' || y == '-' || y == ')' || y == '#')
return da ;
else
return xiao ;
}
else if (x == '*'||x=='/'){
if (y == '+' || y == '-' || y == '*' || y == '/' || y == ')' || y == '#')
return da ;
else
return xiao ;
}
else if (x == '('){
if (y == ')')
return deng;
else
return xiao ;
}
else if (x == ')')
return da ;
else{
if (y == '#')
return deng;
else
return xiao ;
}
}
//運算
ElemType Operate(ElemType a, ElemType x, ElemType b){
int c = a - '0',d = b - '0';
ElemType sum;
if (x == '+')
sum=(c + d + '0');
else if (x == '-')
sum=(c - d + '0');
else if (x == '*')
sum=(c*d + '0');
else
sum=(c / d + '0');
return sum;
}
//表達式求值
//1.輸入必須正確輸入算符(運算符+界限符)和操作數,若輸入非(算符和操作數),無法判斷出(因爲默認非算符的數都爲操作數,否則無法保留兩位數及以上的運算結果)
//2.輸入的操作數必須爲個位數,因爲輸入類型是字符,只能讀取一個字符
//3.輸入類型不能是int型,int無法寫入算符
//表達式以#開頭#結尾,開頭的#用程序寫,壓入棧,結尾的#通過鍵盤輸入
int EvaluateExpression(){
StackLink OPND, OPTR;
InitStack(OPND);//初始化OPND棧,寄存操作數或運算結果
InitStack(OPTR);//初始化OPTR棧,寄存算符
Push(OPTR, '#');//表達式起始符#入棧
ElemType p,theta,a,b;//p是鍵盤輸入的,theta,a和b是算符和兩個操作數(當輸入爲算符且優先級高時運算用:a theta b)
cin >> p;
while (p != '#'||GetHead(OPTR)!='#'){//表達式沒有掃描完畢或OPTR的棧頂元素不爲‘#’
//如果是算符就比較優先級(當出現優先級高的算符就運算,優先級低的就入棧)
if (p == '+' || p == '-' || p == '*' || p == '/' || p == '(' || p == ')'||p=='#')
switch (Precede(GetHead(OPTR),p))
{
case xiao://若優先級低,先把算符壓入OPTR不計算
Push(OPTR, p);
cin >> p;
break;
case da://若優先級高,則進行運算,彈出OPTR棧頂的算符和OPND的兩個數
//輸入)的情況下優先級總是高【(則等於,可消掉括號】,前一個算符參與後運算不輸入新p,)會循環到下一次和前一個算符再比較優先級直到遇到(
Pop(OPTR, theta);//p爲彈出的算符
Pop(OPND, b);//先出的是後進的
Pop(OPND, a);//後出的是先進的
Push(OPND, Operate(a, theta, b));//運算結果壓入OPND
break;
case deng://若優先級相等(只有()和##兩種情況)則括號匹配成功,消去棧頂的(/#並且不讓p入棧,寫新p
//(##其實不會出現,當p爲#且棧頂元素爲#時就退出循環了已經)
Pop(OPTR, p);//p是彈出的廢棄算符
cin >> p;
break;
default:
return -1;
}
//如果是操作數就入棧OPND
else{
Push(OPND, p);
cin >> p;
}
}
int sum = GetHead(OPND)-'0';
return sum;
}
int main(){
printf("結果是:%d",EvaluateExpression());
system("PAUSE");
return 0;
}
0.結構體和枚舉類型
注意枚舉元素得是字母與數字組成的符號序列
typedef enum {da , xiao, deng, ERROR }pre;//枚舉元素得是字母與數字組成的符號序列
typedef char ElemType;
typedef struct StackNode* StackLink;
struct StackNode{
ElemType data;
StackLink next;
};
1.鏈棧的基本操作
//初始化
void InitStack(StackLink &S){
S = NULL;
return;
}
//入棧
void Push(StackLink &S, ElemType e){
StackLink p = (StackLink)malloc(sizeof(StackNode));
p->data = e;
p->next = S;
S = p;
return;
}
//出棧
void Pop(StackLink &S, ElemType &e){
e = S->data;
S = S->next;
return;
}
//返回棧頂元素
ElemType GetHead(StackLink S){
if (S == NULL)return 0;
return S->data;
}
//堆棧判空
bool StackEmpty(StackLink S){
if (S == NULL)return true;
return false;
}
2.表達式求值
2.1算符判斷優先值
typedef enum {da , xiao, deng, ERROR }pre;//枚舉元素得是字母與數字組成的符號序列
typedef char ElemType;
typedef struct StackNode* StackLink;
//算符判斷優先級
pre Precede(ElemType x,ElemType y){
if ((x == '('&&y == '#') || (x == ')'&&y == '(') || (x == '#'&&y == ')'))
return ERROR;
else if (x == '+'||x=='-'){
if (y == '+' || y == '-' || y == ')' || y == '#')
return da ;
else
return xiao ;
}
else if (x == '*'||x=='/'){
if (y == '+' || y == '-' || y == '*' || y == '/' || y == ')' || y == '#')
return da ;
else
return xiao ;
}
else if (x == '('){
if (y == ')')
return deng;
else
return xiao ;
}
else if (x == ')')
return da ;
else{
if (y == '#')
return deng;
else
return xiao ;
}
}
2.2優先級較大情況下的運算
//運算
ElemType Operate(ElemType a, ElemType x, ElemType b){
int c = a - '0',d = b - '0';
ElemType sum;
if (x == '+')
sum=(c + d + '0');
else if (x == '-')
sum=(c - d + '0');
else if (x == '*')
sum=(c*d + '0');
else
sum=(c / d + '0');
return sum;
}
2.3求值步驟(求值的主體函數)
注意
1.輸入
——1.1.輸入必須正確輸入算符(運算符+界限符)和操作數,若輸入非(算符和操作數),無法判斷出(因爲默認非算符的數都爲操作數,否則無法保留兩位數及以上的運算結果)
——1.2.輸入的操作數必須爲個位數,因爲輸入類型是字符,只能讀取一個字符
——1.3.輸入類型不能是int型,int無法寫入算符
2表達式以#開頭#結尾,開頭的#用程序寫,壓入棧,結尾的#通過鍵盤輸入
int EvaluateExpression(){
StackLink OPND, OPTR;
InitStack(OPND);//初始化OPND棧,寄存操作數或運算結果
InitStack(OPTR);//初始化OPTR棧,寄存算符
Push(OPTR, '#');//表達式起始符#入棧
ElemType p,theta,a,b;//p是鍵盤輸入的,theta,a和b是算符和兩個操作數(當輸入爲算符且優先級高時運算用:a theta b)
cin >> p;
while (p != '#'||GetHead(OPTR)!='#'){//表達式沒有掃描完畢或OPTR的棧頂元素不爲‘#’
//如果是算符就比較優先級(當出現優先級高的算符就運算,優先級低的就入棧)
if (p == '+' || p == '-' || p == '*' || p == '/' || p == '(' || p == ')'||p=='#')
switch (Precede(GetHead(OPTR),p))
{
case xiao://若優先級低,先把算符壓入OPTR不計算
Push(OPTR, p);
cin >> p;
break;
case da://若優先級高,則進行運算,彈出OPTR棧頂的算符和OPND的兩個數
//輸入)的情況下優先級總是高【(則等於,可消掉括號】,前一個算符參與後運算不輸入新p,)會循環到下一次和前一個算符再比較優先級直到遇到(
Pop(OPTR, theta);//p爲彈出的算符
Pop(OPND, b);//先出的是後進的
Pop(OPND, a);//後出的是先進的
Push(OPND, Operate(a, theta, b));//運算結果壓入OPND
break;
case deng://若優先級相等(只有()和##兩種情況)則括號匹配成功,消去棧頂的(/#並且不讓p入棧,寫新p
//(##其實不會出現,當p爲#且棧頂元素爲#時就退出循環了已經)
Pop(OPTR, p);//p是彈出的廢棄算符
cin >> p;
break;
default:
return -1;
}
//如果是操作數就入棧OPND
else{
Push(OPND, p);
cin >> p;
}
}
int sum = GetHead(OPND)-'0';
return sum;
}
主函數
int main(){
printf("結果是:%d",EvaluateExpression());
system("PAUSE");
return 0;
}