Loading

简易计算器

输入一串包含 + - * / () 的算式,给出计算结果的简单程序。

#include <cstring>
#include <iostream>

#define MAX_STACK 256

// 读取括号内的范围
int readBracket(char expr[], int &index)
{
	// index 是初始括号 ( 的下一个索引
	int level = 1; // 层级,表示括号的层数
	while (level > 0)
	{
		char c = expr[index++];
		switch (c)
		{
		case '(':
			level++;
			break;
		case ')':
			level--;
			break;
		}
	}
	// 最后 index 移动到括号 ) 后一位,因此 -1 就是 ) 的索引
	return index - 1;
}

// 读取一个数
double getNum(char expr[], int &index)
{
	double num = expr[index] - '0';
	while (expr[++index] >= '0' && expr[index] <= '9')
	{
		num = num * 10 + expr[index] - '0';
	}
	return num;
}

// 计算指定范围内的表达式,其中 tmp 存放的是表达式最初的值
double calculate(char expr[], int left, int right, double res = 0, bool sign = false)
{
	char c;
	int index = left;
	// 存放临时值
	double tmp = 0;

	while (index < right)
	{
		c = expr[index];
		// 考虑变号
		if (sign)
		{
			if (c == '+')
			{
				c = '-';
			}
			else if (c == '-')
			{
				c = '+';
			}
		}
		switch (c)
		{
			// 遇到加减,直接返回两边相加的结果
		case '+':
			// 出现括号
			if (expr[++index] == '(')
			{
				// 获取 ( 之后一位
				int l = ++index;
				int r = readBracket(expr, index);
				// 括号中的值
				tmp = calculate(expr, l, r);
			}
			// 上面表达式的值作为右边式子的初始值
			res += calculate(expr, index, right, tmp);
			return res;
		case '-':
			// 出现括号
			if (expr[++index] == '(')
			{
				// 获取 ( 之后一位
				int l = ++index;
				int r = readBracket(expr, index);
				// 括号中的值
				tmp = calculate(expr, l, r);
			}
			// 上面表达式的值作为右边式子的初始值
			// 进行减法递归时,右边部分的符号要发生变化,具体来说是与当前符号状态相反
			res -= calculate(expr, index, right, tmp, !sign);
			return res;
		case '*':
			// 出现括号
			if (expr[++index] == '(')
			{
				// 获取 ( 之后一位
				int l = ++index;
				int r = readBracket(expr, index);
				// 括号中的值
				res *= calculate(expr, l, r);
			}
			else
			{
				res *= getNum(expr, index);
			}
			break;
		case '/':
			// 出现括号
			if (expr[++index] == '(')
			{
				// 获取 ( 之后一位
				int l = ++index;
				int r = readBracket(expr, index);
				// 括号中的值
				res /= calculate(expr, l, r);
			}
			else
			{
				res /= getNum(expr, index);
			}
			break;
			// 开头出现括号
		case '(':
		{
			// 从下一个开始读取,获得括号最右边 ) 的位置
			int l = ++index;
			int r = readBracket(expr, index);
			res += calculate(expr, l, r);
		}
		break;
		default:
			// 否则是在读第一个数
			res += getNum(expr, index);
			break;
		}
	}
	return res;
}

void calculator()
{
	char c;
	char expr[MAX_STACK];
	do
	{
		std::cout << "输入一个算式:" << std::endl;
		int index = 0;
		memset(expr, 0, MAX_STACK);
		// 输入回车或超出限制就结束
		while ((c = getchar()) != '\n' && index < MAX_STACK)
		{
			if (c == ' ')
			{
				continue;
			}
			expr[index] = c;
			index++;
		}
		std::cout << "计算结果为:" << " = " << calculate(expr, 0, strlen(expr)) << std::endl
				  << std::endl;
		std::cout << "是否继续?y/n" << std::endl;
		c = getchar();
		// 用于存放回车
		getchar();
		std::cout << std::endl;
	} while (c != 'n');
}

int main()
{
	calculator();
	return 0;
}
posted @ 2022-03-07 20:36  Bluemultipl  阅读(52)  评论(0编辑  收藏  举报