栈实现计算器

本文介绍了一种使用栈实现将中缀表达式转换为后缀表达式的方法,并通过算法进行计算得出结果。代码示例涵盖了操作符优先级处理、数值输入解析等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include"StdAfx.h"
#include <iostream>
#include<stack>
using namespace std;
stack<int>sdata;
stack<char>soper;

int isoper(char c)
{
	if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='#')
		return 1;
	else
		return 0;
}
char percede(char s,char c)
{
	switch(s)
	{
	case'+':
	case'-':
		{
		if(c=='+'||c=='-')
			return '>';
		else if(c=='*'||c=='/')
			return '<';
		else if(c=='(')
			return '<';
		else if(c==')')
			return '>';
		else 
			return '>';
		}
		break;
	case'*':
	case'/':
		{
		if(c=='+'||c=='-')
			return '>';
		else if(c=='*'||c=='/')
			return '>';
		else if(c=='(')
			return '<';
		else if(c==')')
			return '>';
		else 
			return '>';
		}
		break;
	case'(':
		{
			if(c==')')
				return '=';
			else 
				return '<';
		}
		break;
	case')':
		{
			return '>';
		}
		break;
	case'#':
		{
			if(c=='#')
				return '=';
			else
				return '<';

		}
		break;
	}
}
int operater(int x,char op,int y)
{
	int s;
	switch(op)
	{
	case'+':
		s=x+y;
		break;
	case'-':
		s=x-y;
		break;
	case'*':
		s=x*y;
		break;
	case'/':
		s=x/y;
		break;
	}
	return s;
}
int main()
{
	int a,b,result,i;
	char ch,thre;
	sdata.empty();
	soper.empty();
	soper.push('#');
	ch=getchar();
	while(ch!='#' || soper.top()!='#')
	{
		if(!isoper(ch))
		{
			i=atoi(&ch);
			ch=getchar();
			while(!isoper(ch))
			{
				i=i*10+atoi(&ch);
				ch=getchar();
			}
			sdata.push(i);
		}
		else
		{
			switch(percede(soper.top(),ch))
			{
			case'<':
				{
					soper.push(ch);
					ch=getchar();
				}
				break;
			case'=':
				{
					thre=soper.top();
					soper.pop();
					ch=getchar();
				}
				break;
			case'>':
				{
					thre=soper.top();
					soper.pop();
					b=sdata.top();
					sdata.pop();
					a=sdata.top();
					sdata.pop();
					result=operater(a,thre,b);
					sdata.push(result);
				}
				break;
			}
		}
	}
	cout<<result<<endl;
//	system("pause");
	return 0;
}

<think>我们使用实现一个计算器,能够处理加减乘除和括号的表达式。基本思路是使用两个:一个操作数(存放数字),一个运算符(存放运算符)。算法遵循以下步骤:1.初始化两个,运算符可以先压入一个优先级最低的运算符(如'#')作为哨兵。2.从左到右扫描表达式:a.如果是数字,则读取完整的数字(可能有多位和小数点),然后压入操作数。b.如果是运算符(包括括号):i.如果当前运算符是左括号'(',直接压入运算符。ii.如果当前运算符是右括号')',则不断弹出运算符顶的运算符并计算,直到遇到左括号(左括号弹出但不计算)。iii.如果是其他运算符(加减乘除),则与运算符顶的运算符比较优先级:-若当前运算符优先级高于顶运算符,则压入。-否则,弹出顶运算符并计算(从操作数弹出两个操作数),然后将当前运算符压入。3.当表达式扫描完后,如果运算符中还有运算符,则依次弹出并计算。4.最后操作数中剩下的一个数就是结果。注意:需要处理运算符的优先级,我们定义优先级:'(' >'*'='/' >'+' ='-' >'#',但是注意在中,左括号只有在遇到右括号时才弹出,所以左括号在内时优先级可以认为较低,但在外(即当前扫描到的)优先级较高。具体实现时,我们用一个函数来比较优先级:顶运算符和当前运算符。下面我们给出C语言的实现代码。由于C语言没有内置,我们需要自己实现的基本操作(初始化、入、出、取顶等)。注意:本实现假设输入的表达式是合法的,并且只包含数字、加减乘除和括号,以及小数点。我们使用字符串来存储表达式。步骤:1.定义结构及基本操作。 2.实现计算器类,包括读取数字、读取运算符、优先级比较、计算函数和主计算函数。由于用户要求使用C语言,我们将用C语言实现。注意:我们使用数组来实现(固定大小),并假设表达式长度不超过一定限制。代码实现如下:</think>### C语言实现计算器算法详解 我们将使用两个(操作数和运算符实现支持加减乘除和括号的四则运算计算器。核心算法基于运算符优先级比较和操作,以下是完整实现: ```c #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include <math.h> #define MAX_SIZE 100 // 结构定义 typedef struct { double data[MAX_SIZE]; int top; } NumStack; // 操作数 typedef struct { char data[MAX_SIZE]; int top; } OprStack; // 运算符 // 初始化 void initNumStack(NumStack* s) { s->top = -1; } void initOprStack(OprStack* s) { s->top = -1; } // 操作函数 void pushNum(NumStack* s, double val) { if (s->top < MAX_SIZE - 1) s->data[++(s->top)] = val; } double popNum(NumStack* s) { if (s->top >= 0) return s->data[(s->top)--]; return 0; } void pushOpr(OprStack* s, char op) { if (s->top < MAX_SIZE - 1) s->data[++(s->top)] = op; } char popOpr(OprStack* s) { if (s->top >= 0) return s->data[(s->top)--]; return '\0'; } char topOpr(OprStack* s) { if (s->top >= 0) return s->data[s->top]; return '\0'; } // 运算符优先级判断 int precedence(char op) { switch (op) { case '+': case '-': return 1; case '*': case '/': return 2; case '(': return 0; // 括号特殊处理 default: return -1; } } // 执行二元运算 void calculate(NumStack* numStack, char op) { double b = popNum(numStack); double a = popNum(numStack); switch (op) { case '+': pushNum(numStack, a + b); break; case '-': pushNum(numStack, a - b); break; case '*': pushNum(numStack, a * b); break; case '/': if (fabs(b) < 1e-6) { fprintf(stderr, "Error: Division by zero\n"); exit(EXIT_FAILURE); } pushNum(numStack, a / b); break; } } // 主计算函数 double evaluateExpression(const char* expr) { NumStack numStack; OprStack oprStack; initNumStack(&numStack); initOprStack(&oprStack); pushOpr(&oprStack, '#'); // 哨兵运算符 int i = 0; while (expr[i] != '\0') { // 处理数字(含小数) if (isdigit(expr[i]) || expr[i] == '.') { char numStr[20]; int j = 0; while (isdigit(expr[i]) || expr[i] == '.') { numStr[j++] = expr[i++]; } numStr[j] = '\0'; pushNum(&numStack, atof(numStr)); continue; } // 处理运算符 else if (strchr("+-*/()", expr[i])) { char currentOp = expr[i]; // 左括号直接入 if (currentOp == '(') { pushOpr(&oprStack, currentOp); } // 右括号:计算直到匹配左括号 else if (currentOp == ')') { while (topOpr(&oprStack) != '(') { calculate(&numStack, popOpr(&oprStack)); } popOpr(&oprStack); // 弹出左括号 } // 普通运算符:比较优先级 else { while (precedence(currentOp) <= precedence(topOpr(&oprStack))) { calculate(&numStack, popOpr(&oprStack)); } pushOpr(&oprStack, currentOp); } i++; } // 跳过空格 else if (isspace(expr[i])) { i++; } // 非法字符处理 else { fprintf(stderr, "Error: Invalid character '%c'\n", expr[i]); exit(EXIT_FAILURE); } } // 处理中剩余运算符 while (topOpr(&oprStack) != '#') { calculate(&numStack, popOpr(&oprStack)); } return popNum(&numStack); } int main() { char expression[100]; printf("输入表达式 (支持+-*/()): "); fgets(expression, sizeof(expression), stdin); expression[strcspn(expression, "\n")] = '\0'; // 移除换行符 double result = evaluateExpression(expression); printf("结果: %.2f\n", result); return 0; } ``` ### 算法核心逻辑 1. **双结构**: - 操作数 (`NumStack`):存储运算数字 - 运算符 (`OprStack`):存储运算符和括号 2. **优先级处理**: - 运算符优先级:`*/` > `+-` > `(` - 遇到高优先级运算符时先计算顶操作 - 括号特殊处理:左括号直接入,右括号触发内计算直到左括号 3. **计算流程**: ```mermaid graph TD A[开始] --> B{扫描字符} B -->|数字| C[读取完整数字入操作数] B -->|运算符| D{是括号?} D -->|'('| E[直接入运算符] D -->|')'| F[计算直到弹出'('] D -->|其他| G[比较优先级并计算] B -->|结束| H[计算内剩余操作] H --> I[返回结果] ``` 4. **关键函数**: - `precedence()`:定义运算符优先级 - `calculate()`:执行二元运算 - `evaluateExpression()`:主调度函数 ### 示例运算过程 对于表达式 `3*(5-2)+4`: 1. 操作数:`[3]` → `[3,5]` → `[3,5,2]` 2. 运算符:`[#]` → `[#, *]` → `[#, *, (]` → `[#, *]` (遇到`-`) 3. 计算 `5-2=3` → 操作数变为 `[3,3]` 4. 计算 `3*3=9` → 操作数 `[9]` 5. 继续处理 `+4` → 最终结果 `13` ### 注意事项 1. 支持小数运算(如 `3.14*2`) 2. 错误检测:除零错误、非法字符 3. 括号必须成对出现 4. 输入表达式不应包含空格以外的特殊字符 此实现完整展示了在表达式求值中的应用,通过运算符优先级管理实现了正确的计算顺序[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值