使用棧來實現含括號的四則運算,複雜的就是各種分支的判斷,當時參考了很多前輩的代碼,又自己敲了很久,得到一個最終版,在此記錄一下,希望若干年後的自己看到時能夠不忘初心。
#include<stdio.h>
#include<stdlib.h>
/*數據棧*/
struct shuju {
float data[100];
int top;
};
/*符號棧*/
struct fuhao {
char symbol[100];
int top;
};
void InitOperateNum(struct shuju *StackNum)
{
StackNum->top = -1;
}
void InitOperateSymbol(struct fuhao *StackSymbol)
{
StackSymbol->top = -1;
}
/*存入數據棧*/
void Inshuju(struct shuju *StackNum, int num)
{
StackNum->top ++;
StackNum->data[StackNum->top] = num;
}
/*存入符號棧*/
void Infuhao(struct fuhao *StackSymbol, char ch)
{
StackSymbol->top ++;
StackSymbol->symbol[StackSymbol->top] = ch;
}
/*讀取數據棧*/
int Readshuju(struct shuju *StackNum)
{
return StackNum->data[StackNum->top];
}
/*讀取符號棧*/
char Readfuhao(struct fuhao *StackSymbol)
{
return StackSymbol->symbol[StackSymbol->top];
}
/*從數據棧取出數據*/
int Putshuju(struct shuju *StackNum)
{
int x;
x = StackNum->data[StackNum->top];
StackNum->top --;
return x;
}
/*從符號棧取出符號*/
char Putfuhao(struct fuhao *StackSymbol)
{
char c;
c = StackSymbol->symbol[StackSymbol->top];
StackSymbol->top --;
return c;
}
/*符號優先級判斷*/
int judge(char ch) {
if(ch == '(') {
return 1;
}
if(ch == '+' || ch == '-') {
return 2;
}
else if(ch == '*' || ch == '/') {
return 3;
}
else if(ch == ')') {
return 4;
}
}
/*四則運算*/
int Math(float v1, float v2, char c)
{
float sum;
switch(c) {
case '+' : {
sum = v1 + v2;
break;
}
case '-' : {
sum = v1 - v2;
break;
}
case '*' : {
sum = v1 * v2;
break;
}
case '/' : {
sum = v1 / v2;
break;
}
}
return sum;
}
void manu(){
printf("**********************************************************\n");
printf("\t算術運算菜單\n");
printf("1、加法運算\n");
printf("2、減法運算\n");
printf("3、乘法運算\n");
printf("4、除法運算\n");
printf("5、混合運算(無括號)\n");
printf("6、混合運算(有括號)\n");
printf("0、輸入0退出程序\n");
printf("**********************************************************\n");
}
int main()
{
while(1){
manu();
printf("請輸入表達式:");
struct shuju data;
struct fuhao symbol;
InitOperateNum(&data);
InitOperateSymbol(&symbol);
int i, t;
float v1, v2;
float sum;
char c;
i = t = 0;
sum =0;
char v[100] = {0};
char *str = (char *)malloc(sizeof(char)*200);
while((c = getchar()) != '\n') {
str[i] = c;
i ++;
}
str[i] = '\0';
for(i = 0; str[i] != '\0'; i ++) {
if(i == 0 && str[i] == '-') {
v[t++] = str[i];
}
else if(str[i] == '(' && str[i+1] == '-') {
i ++;
v[t++] = str[i++];
while(str[i] >= '0' && str[i] <= '9') {
v[t] = str[i];
t ++;
i ++;
}
Inshuju(&data, atoi(v));
while(t > 0) {
v[t] = 0;
t --;
}
if(str[i] != ')') {
i --;
Infuhao(&symbol, '(');
}
}
else if(str[i] >= '0' && str[i] <= '9') {
while(str[i] >= '0' && str[i] <= '9') {
v[t] = str[i];
t ++;
i ++;
}
Inshuju(&data, atoi(v));
while(t > 0) {
v[t] = 0;
t --;
}
i --;
}
else {
if(symbol.top == -1) { //如果符號棧沒有元素,直接把符號放入符號棧
Infuhao(&symbol, str[i]);
}
else if(judge(str[i]) == 1) { //如果此符號是'(',直接放入符號棧
Infuhao(&symbol, str[i]);
}
else if(judge(str[i]) == 2) { //如果此符號是'+'或'-',判斷與棧頂符號是優先級
if(judge(Readfuhao(&symbol)) == 1) { //如果棧頂符號是'(',放入符號棧
Infuhao(&symbol, str[i]);
}
else if(judge(Readfuhao(&symbol)) == 2) { //如果棧頂符號是'+'或'-',則出棧運算
while(symbol.top >= 0 && data.top >= 1) { //循環出棧
v2 = Putshuju(&data);
v1 = Putshuju(&data);
sum = Math(v1, v2, Putfuhao(&symbol));
Inshuju(&data, sum); //將運算結果壓入數據棧
}
Infuhao(&symbol, str[i]); //新符號進棧
}
else if(judge(Readfuhao(&symbol)) == 3) { //如果棧頂符號是'*'或'/',則進符號棧
while(symbol.top >= 0 && data.top >= 1) { //循環出棧
v2 = Putshuju(&data);
v1 = Putshuju(&data);
sum = Math(v1, v2, Putfuhao(&symbol));
Inshuju(&data, sum); //將運算結果壓入數據棧
}
Infuhao(&symbol, str[i]); //新符號進棧
}
/*棧頂符號不可能是')',故不做判斷*/
}
else if(judge(str[i]) == 3) { //如果此符號是'*'或'/',則判斷與棧頂符號是優先級
if(judge(Readfuhao(&symbol)) == 1) { //如果棧頂符號是'(',放入符號棧
Infuhao(&symbol, str[i]);
}
else if(judge(Readfuhao(&symbol)) == 2) { //如果棧頂符號是'+'或'-',則進符號棧
Infuhao(&symbol, str[i]); //新符號進棧
}
else if(judge(Readfuhao(&symbol)) == 3) { //如果棧頂符號是'*'或'/',則出棧運算
while(symbol.top >= 0 && data.top >= 1) { //循環出棧
v2 = Putshuju(&data);
v1 = Putshuju(&data);
sum = Math(v1, v2, Putfuhao(&symbol));
Inshuju(&data, sum); //將運算結果壓入數據棧
}
Infuhao(&symbol, str[i]); //新符號進棧
}
}
else if(judge(str[i]) == 4) { // 如果棧頂符號是')',則出棧運算直到遇到'('
do { //循環出棧直到遇到'('
v2 = Putshuju(&data);
v1 = Putshuju(&data);
sum = Math(v1, v2, Putfuhao(&symbol));
Inshuju(&data, sum); //將運算結果壓入數據棧
}while(judge(Readfuhao(&symbol)) != 1);
Putfuhao(&symbol); //括號內運算結束後使'('出棧
}
}
}
free(str); //釋放內存空間
while(symbol.top != -1) {
v2 = Putshuju(&data);
v1 = Putshuju(&data);
sum = Math(v1, v2, Putfuhao(&symbol));
Inshuju(&data, sum);
}
printf("%.2f\n", data.data[0]);
}
return 0;
}