1. 程式人生 > >使用C語言與棧實現簡單多則運算計算器(包括括號優先順序運算)

使用C語言與棧實現簡單多則運算計算器(包括括號優先順序運算)

#include <stdio.h>
#include <stdlib.h> 
#define MAX 20
//定義第一個棧---作為存放運算數的操作符 
struct SNode_Num
{
	int datas[MAX];
	int top;
};
typedef struct SNode_Num OperateNum;

//定義第二個棧---作為存放運算子號的棧 
struct SNode_Symbol
{
	char symbol[MAX];
	int top;
};
typedef struct SNode_Symbol OperateSymbol;

/********************************************************************
描述:定義函式:InitOperandNum,並且初始化運算數棧頂 
引數:OperateNum *StackNum
返回值:void
********************************************************************/
void InitOperateNum(OperateNum *StackNum)
{
	StackNum->top = -1; 
}

/********************************************************************
描述:定義函式: InitOperateSymbol,並且初始化運算子棧頂 
引數:OperateSymbol *StackSymbol
返回值:void
********************************************************************/
void InitOperateSymbol(OperateSymbol *StackSymbol)
{
	StackSymbol->top = -1;
} 

/********************************************************************
描述:定義函式:PushOperateNum, 壓一個數到棧頂 
引數:OperateNum *StackNum, int x 
返回值:void 
********************************************************************/
void PushOperateNum(OperateNum *StackNum, int x)
{
	StackNum->top++;
	StackNum->datas[StackNum->top] = x; 
} 

/********************************************************************
描述:定義函式:PushOperateSymbol,壓一個運算子到棧頂 
引數:OperateSymbol *StackSymbol, char ch
返回值:void 
********************************************************************/
void PushOperateSymbol(OperateSymbol *StackSymbol, char ch)
{
	StackSymbol->top++;
	StackSymbol->symbol[StackSymbol->top] = ch; 
}

/********************************************************************
描述:定義函式:PopOperateNum,將運算數從棧中讀取出來 
引數:OperateNum *StackNum
返回值:返回取出來的數 
********************************************************************/
int PopOperateNum(OperateNum *StackNum)
{
	int num;
	num = StackNum->datas[StackNum->top];
	StackNum->top--;
	return num;
}

/********************************************************************
描述:定義函式:PopOperateSymbol,將運算子從棧中取出來 
引數:OperateSymbol *StackSymbol
返回值:返回取出來的符號 
********************************************************************/
char PopOperateSymbol(OperateSymbol *StackSymbol)
{
	char ch;
	ch = StackSymbol->symbol[StackSymbol->top];
	StackSymbol->top--;
	return ch;
}

//取出相應的數 
int GetOperateNum(OperateNum *StackNum)
{
	return StackNum->datas[StackNum->top];
}

//取出相應運算子 
char GetOperateSymbol(OperateSymbol *StackSymbol)
{
	return StackSymbol->symbol[StackSymbol->top]; 
} 

/********************************************************************
描述:定義函式, IsOperateSymbolOrNum,判斷輸入的符號是那些符號 
引數:char ch
返回值:有符號返回1,無符號返回0 
********************************************************************/
short IsOperateSymbolOrNum(char ch)
{
	//判斷所有需要用的操作符 包括 + - * / ( ) \n 
	if(ch == '+' || ch == '-' || ch == '*' 
	|| ch == '/' || ch == '(' || ch == ')' || ch == '\n') return 1;
	
	else return 0;	
}

/********************************************************************
描述:定義函式: Priority,用於判斷符號優先順序運算 
引數:char inputnum, char ch
返回值:符號的大小的字元 
********************************************************************/
char Priority(char inputnum, char ch)
{
	switch(inputnum)
	{
		//加減在同一個優先順序上 
		case '+':
		case '-':
		{
			if(ch == '+' || ch == '-') return '>';
			else if(ch == '*' || ch == '/') return '<';
			else if(ch == '(') return '<';
			else if(ch == ')') return '>';
			else return '>';	
		}
			break;
		
		//乘除在同一優先順序 
		case '*':
		case '/':
		{
			if(ch == '+' || ch == '-') return '>';
			else if(ch == '*' || ch == '/') return '>';
			else if(ch == '(') return '<';
			else if(ch == ')') return '>';
			else return '>';
		}
			break;
		
		//括號在所有優先順序以上 
		case '(':
		{
			if(ch == ')') return '=';
			else return '<';
		}
			break;
		case ')':
		{
			return '>';
		}
			break;
		case '\n':
		{
			if(ch == '\n') return '=';
			else return '<';
		}
			break;	
	}
}

/********************************************************************
描述:定義函式: Calculate,計算結果 
引數:int num1, char ch, int num2
返回值:返回兩個數計算的結果result 
********************************************************************/
int Calculate(int num1, char ch, int num2)
{
	int result;
	switch(ch)
	{
		case '+':
			result = num1 + num2;
			break;
		case '-':
			result = num1 - num2; 
			break;
		case '*':
			result = num1 * num2;
			break;
		case '/':
			result = num1 / num2;
	}
	return result;
}

/********************************************************************
描述:定義函式:MainCalc,主要用於獲取使用者輸入,並且進行計算 
引數:void 
返回值:result
********************************************************************/
int MainCalc()
{
	//主函式進行計算 
	OperateNum datas;
	OperateSymbol symbol;
	int num1, num2, result, num;
	char ch, sign;
	
	InitOperateNum(&datas);
	InitOperateSymbol(&symbol);
	
	
	//把回車計算的操作符放在棧中 
	PushOperateSymbol(&symbol, '\n');
	ch = getchar();
	while((ch != '\n') || (GetOperateSymbol(&symbol) != '\n'))
	{
		if(!IsOperateSymbolOrNum(ch))
		{
			num = atoi(&ch);  //將字元轉換為整數
			ch = getchar();   //獲取輸入
			while(!IsOperateSymbolOrNum(ch))
			{
				num = num * 10 + atoi(&ch);
				ch = getchar();   //當沒有輸入回車時,繼續獲取輸入
			} 
			PushOperateNum(&datas, num);			
		}
		else
		{
			switch(Priority(GetOperateSymbol(&symbol), ch))
			{
				//判斷優先順序後進行計算 
				case '<':
					PushOperateSymbol(&symbol, ch);
					ch = getchar();
					break;
				case '=':
					sign = PopOperateSymbol(&symbol);
					ch = getchar();  //獲取輸入
					break;
				case '>':
					sign = PopOperateSymbol(&symbol);
					num2 = PopOperateNum(&datas);
					num1 = PopOperateNum(&datas);
					result = Calculate(num1, sign, num2);
					PushOperateNum(&datas, result);
					break;
					 
			}
		} 
	} 
	result = GetOperateNum(&datas);
	return result;
}

int main(int argc, char *argv[])
{
	int result;
	result = MainCalc();
	printf("%d", result);  //輸出結果 
	
	return 0;
}

歡迎關注我的個人Blog:[我的blog](https://www.finen.top)