【栈】224. 基本计算器

本文涉及知识点

LeetCode 224. 基本计算器

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

示例 1:

输入:s = “1 + 1”
输出:2
示例 2:

输入:s = " 2-1 + 2 "
输出:3
示例 3:

输入:s = “(1+(4+5+2)-3)+(6+8)”
输出:23

提示:

1 <= s.length <= 3 * 105
s 由数字、‘+’、‘-’、‘(’、‘)’、和 ’ ’ 组成
s 表示一个有效的表达式
‘+’ 不能用作一元运算(例如, “+1” 和 “+(2 + 3)” 无效)
‘-’ 可以用作一元运算(即 “-1” 和 “-(2 + 3)” 是有效的)
输入中不存在两个连续的操作符
每个数字和运行的计算将适合于一个有符号的 32位 整数

由于只有 加、减、负号,所有不需要操作数栈,只需要操作符栈,±(三种。数值直接运算。

操作数

当前栈,负号的总数为偶数,则将当前数值加到结果,否则从结果中减去当前值。
如果当前栈顶为±,出栈。

左括号、+、-

入栈

右括号

出栈括号,及前面的±号。

注意:cnt 记录栈中负号的数量。

代码

核心代码

class Solution {
public:
	int calculate(string s) {
		int iRet = 0;
		for (int i = 0; i < s.length(); i++) {
			if (' ' == s[i]) { continue; }
			if (('(' == s[i]) || ('+' == s[i])) {
				m_sta.emplace(s[i]);
			}
			else if('-' == s[i]) {
				m_sta.emplace(s[i]);
				m_iCnt++;
			}
			else if (')' == s[i]) {
				m_sta.pop();
				PopSign();
			}
			else {
				int num = 0;
				while (isdigit(s[i])) {
					num = 10 * num + (s[i] - '0');
					i++;
				}
				if (1 & m_iCnt) {
					iRet -= num;
				}
				else {
					iRet += num;
				}
				PopSign();
				i--;
			}
		}
		return iRet;
	}
	void PopSign() {
		if (m_sta.empty() || ('(' == m_sta.top())) { return; }
		if ('-' == m_sta.top()) { m_iCnt--; };
		m_sta.pop();
	}
	stack<char> m_sta;
	int m_iCnt = 0;
};

单元测试

template<class T1,class T2>
void AssertEx(const T1& t1, const T2& t2)
{
	Assert::AreEqual(t1 , t2);
}

template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{
	Assert::AreEqual(v1.size(), v2.size());	
	for (int i = 0; i < v1.size(); i++)
	{
		Assert::AreEqual(v1[i], v2[i]);
	}
}

template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{
	sort(vv1.begin(), vv1.end());
	sort(vv2.begin(), vv2.end());
	Assert::AreEqual(vv1.size(), vv2.size());
	for (int i = 0; i < vv1.size(); i++)
	{
		AssertEx(vv1[i], vv2[i]);
	}
}

namespace UnitTest
{
	string s;
	TEST_CLASS(UnitTest)
	{
	public:
		TEST_METHOD(TestMethod0)
		{	
			s = "1 + 1";
			auto res = Solution().calculate(s);
			AssertEx(2,res);
		}
		TEST_METHOD(TestMethod1)
		{
			s =" 2-1 + 2 ";
			auto res = Solution().calculate(s);
			AssertEx(3, res);
		}
		TEST_METHOD(TestMethod2)
		{
			s = "(1+(4+5+2)-3)+(6+8)";
			auto res = Solution().calculate(s);
			AssertEx(23, res);
		}
		TEST_METHOD(TestMethod3)
		{
			s = "2147483647";
			auto res = Solution().calculate(s);
			AssertEx(2147483647, res);
		}

		
	};
}

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
《喜缺全书算法册》以原理、正确性证明、总结为主。
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

  • 26
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是一个基于计算器实现,使用C语言编写。 ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAX_STACK_SIZE 100 typedef enum { OPERATOR, OPERAND } Type; typedef struct { Type type; union { char operator; int operand; }; } Token; typedef struct { Token stack[MAX_STACK_SIZE]; int top; } Stack; void push(Stack *stack, Token token) { if (stack->top == MAX_STACK_SIZE) { fprintf(stderr, "Error: Stack overflow\n"); exit(EXIT_FAILURE); } stack->stack[stack->top++] = token; } Token pop(Stack *stack) { if (stack->top == 0) { fprintf(stderr, "Error: Stack underflow\n"); exit(EXIT_FAILURE); } return stack->stack[--stack->top]; } Token peek(Stack *stack) { if (stack->top == 0) { fprintf(stderr, "Error: Stack underflow\n"); exit(EXIT_FAILURE); } return stack->stack[stack->top - 1]; } int is_operator(char c) { return c == '+' || c == '-' || c == '*' || c == '/'; } int precedence(char c) { switch (c) { case '+': case '-': return 1; case '*': case '/': return 2; default: return 0; } } int evaluate(int a, int b, char operator) { switch (operator) { case '+': return a + b; case '-': return a - b; case '*': return a * b; case '/': return a / b; default: fprintf(stderr, "Error: Invalid operator\n"); exit(EXIT_FAILURE); } } int main() { Stack stack; stack.top = 0; char input[256]; printf("Enter an expression: "); fgets(input, 256, stdin); int length = strlen(input); if (input[length - 1] == '\n') { input[length - 1] = '\0'; } char *ptr = input; while (*ptr != '\0') { if (isdigit(*ptr)) { Token token; token.type = OPERAND; token.operand = strtol(ptr, &ptr, 10); push(&stack, token); } else if (is_operator(*ptr)) { while (stack.top > 0 && peek(&stack).type == OPERATOR && precedence(peek(&stack).operator) >= precedence(*ptr)) { Token operator_token = pop(&stack); Token operand_token_2 = pop(&stack); Token operand_token_1 = pop(&stack); Token result_token; result_token.type = OPERAND; result_token.operand = evaluate(operand_token_1.operand, operand_token_2.operand, operator_token.operator); push(&stack, result_token); } Token token; token.type = OPERATOR; token.operator = *ptr; push(&stack, token); ptr++; } else { fprintf(stderr, "Error: Invalid character '%c'\n", *ptr); exit(EXIT_FAILURE); } } while (stack.top > 1) { Token operator_token = pop(&stack); Token operand_token_2 = pop(&stack); Token operand_token_1 = pop(&stack); Token result_token; result_token.type = OPERAND; result_token.operand = evaluate(operand_token_1.operand, operand_token_2.operand, operator_token.operator); push(&stack, result_token); } Token result_token = pop(&stack); if (stack.top != 0 || result_token.type != OPERAND) { fprintf(stderr, "Error: Invalid expression\n"); exit(EXIT_FAILURE); } printf("Result: %d\n", result_token.operand); return 0; } ``` 使用示例: ``` Enter an expression: 3+4*5 Result: 23 ``` 该计算器实现支持基本的四则运算,并且支持运算符优先级。在实现中,我们使用了一个来存储操作数和运算符,并且在遍历输入表达式时,根据当前字符的类型进行不同的处理,以达到计算表达式的目的。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闻缺陷则喜何志丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值