C++计算表达式(暂时不支持带括号运算)

首先需要下面几个函数作为工具

判断是否是数字和运算符号

bool is_digit(char character) {
	
	return character >= '0' and character <= '9';
}

bool is_operator(char character) {
	
	return character == '+' or character == '-' or character == '*' or character == '/';
}

关于表达式则需要下面这些函数工具

删除空格,每个人输入表达式的风格不一样;比如喜欢在符号前后加空格:36 * 2 - 3

这个时候为了方便处理,将中间的空格去掉

(___uint32是我自己实现的类型,原型typedef unsigned int ___uint32;)

(还有String也是,原型typedef typename std::string String;)

String delete_space(String expression) {
	
	String result;
	
	
	for (___uint32 index = 0; index < expression.length(); index++) {
		
		if (expression[index] == ' ') {
			
			continue;
		
		// 若不是空格则追加	
		} else {
			
			result += expression[index];
		}
	}
	
	return result;
}

还需要下面这个,将表达式切分成一堆tokens,放到vector里面

例如:表达式 "37 * 25 - 48 + 4" 拆分之后就是 "37", "*", "25", "-", "48", "+", "4"

(Token是自定义类型,原型typedef class std::vector<std::string> Token;)

Token get_token(String expression) {
	
	Token result;
	
	String buffer_token;
	
	
	for (___uint32 index = 0; index < expression.length(); index++) {
		
		buffer_token = "";
		
		// 数字 
		if (is_digit(expression[index])) {
			
			while (is_digit(expression[index])) {
				
				buffer_token += expression[index], index++;
			}
			index--;
			
			result.push_back(buffer_token);
		
		// 符号 
		} else if (is_operator(expression[index])) {
			
			// 如果有两个符号,则认定为 二元运算 和 一元运算
			// 例 37*-92
			// 则 |37|*|-92| 
			if (is_operator(expression[index + 1]) and is_digit(expression[index + 2])) {
				
				buffer_token += expression[index], index++;
				result.push_back(buffer_token), buffer_token = "";
				
				buffer_token += expression[index], index++;
				
				while (is_digit(expression[index])) {
					
					buffer_token += expression[index], index++;
				}
				index--;
				
				result.push_back(buffer_token);
			
			// 如果只有一个符号,则认为是 二元运算
			// 例 38*23
			// 则 |38|*|23|	
			} else {
				
				buffer_token += expression[index];
				
				result.push_back(buffer_token);
			}
		}
	}
	
	return result;
}

表达式计算就避免不了字符串跟数字互转

还需要下面这个,将字符串转换成任意类型,具体类型需要stringstream的支持才行

这里也可以扩充一个异常,当泛型类型是stringstream不支持的类型时抛出

(Convert是自实现类,原型typedef typename std::stringstream Convert;)

template<typename typex> typex string_to_typex(String string) {
	
	Convert convert;
	
	typex value;
	
	
	convert << string, convert >> value;
	
	return value;
}

然后就是运算部分了

先乘除后加减

当迭代器位置的字符串是对应运算符的时候,左边的token转换成对应类型之后存储到left,右边的token转换成对应类型之后存储到right,然后ret存储最终结果。

___sint32 替换成 float 可以支持小数

ret计算完之后删掉原来左边的token和中间的token,把ret的值转换成字符串存到原来右边的token里面,实现一次运算。

乘除运算完后再运算加减。

Token operation(Token tokens) {
	
	//
	
	
	// 先扒拉乘除 
	for (Token::iterator iter = tokens.begin(); iter != tokens.end(); iter++) {
		
		if (*iter == "*") {
			
			// 左值,右值,总值 
			___sint32 left = 0, right = 0, ret = 0;
			
			
			// 左值 
			left = string_to_typex<___sint32>(*(iter - 1));
			// 右值 
			right = string_to_typex<___sint32>(*(iter + 1));
			// 总值 
			ret = left * right;
			
			// 把不要的都扔了
			// S								|23|*|89|
			//									    ↑ 
			// iter = tokens.erase(iter - 1);	|*|89|
			//									 ↑ 
			// iter = tokens.erase(iter);		|89|
			//									 ↑ 
			// *iter = std::to_string(ret);		|2047|
			//									 ↑ 
			iter = tokens.erase(iter - 1);
			iter = tokens.erase(iter);
			*iter = std::to_string(ret);
			
		} else if (*iter == "/") {
			
			___sint32 left = 0, right = 0, ret = 0;
			
			
			left = string_to_typex<___sint32>(*(iter - 1));
			right = string_to_typex<___sint32>(*(iter + 1));
			ret = left / right;
			
			iter = tokens.erase(iter - 1);
			iter = tokens.erase(iter);
			*iter = std::to_string(ret);
		}
	}
	
	// 再扒拉加减 
	for (Token::iterator iter = tokens.begin(); iter != tokens.end(); iter++) {
		
		if (*iter == "+") {
			
			___sint32 left = 0, right = 0, ret = 0;
			
			
			left = string_to_typex<___sint32>(*(iter - 1));
			right = string_to_typex<___sint32>(*(iter + 1));
			ret = left + right;
			
			iter = tokens.erase(iter - 1);
			iter = tokens.erase(iter);
			*iter = std::to_string(ret);
			
		} else if (*iter == "-") {
			
			___sint32 left = 0, right = 0, ret = 0;
			
			
			left = string_to_typex<___sint32>(*(iter - 1));
			right = string_to_typex<___sint32>(*(iter + 1));
			ret = left - right;
			
			iter = tokens.erase(iter - 1);
			iter = tokens.erase(iter);
			*iter = std::to_string(ret);
		}
	}
	
	return tokens;
}

最后tokens的第一位则是最终的结果

完整代码如下


// 基本输出输入 
#include <iostream>

// 储存表达式 tokens 
#include <vector>

// 数字与字符串转换 
#include <sstream>


// 测试专用 
#define ___test_for_tokens \
for (___uint32 index = 0; index < tokens.size(); index++) { \
	 \
	std::cout << tokens[index] << ", "; \
}


// 集合类型 
typedef		signed short			___sint16	;
typedef		unsigned short			___uint16	;
typedef		signed int				___sint32	;
typedef		unsigned int			___uint32	;
typedef		signed long	long		___sint64	;
typedef		unsigned long long		___uint64	;

typedef	typename	std::string					String	;
typedef	class		std::vector<std::string>	Token	;
typedef typename	std::stringstream			Convert	;


// 声明 是否是数字 
extern bool is_digit(char);
// 声明 是否是运算符 
extern bool is_operator(char);
// 声明 删除空格 
extern String delete_space(String);
// 声明 切分token 
extern Token get_token(String);
// 声明 string转type x 
template<typename typex> extern typex string_to_typex(String);
// 声明 运算 
extern Token operation(Token);


___sint32 main(___sint32 argument_count, char** arguments) {
	
	String expression;
	
	Token tokens;
	
	
	std::getline(std::cin, expression);
	
	expression = delete_space(expression);
	tokens = get_token(expression);
	
	tokens = operation(tokens);
	
	// ___test_for_tokens;
	
	// 最后结果是token第零个 
	std::cout << tokens[0];
	
	return 0;
}

bool is_digit(char character) {
	
	return character >= '0' and character <= '9';
}

bool is_operator(char character) {
	
	return character == '+' or character == '-' or character == '*' or character == '/';
}

String delete_space(String expression) {
	
	String result;
	
	
	for (___uint32 index = 0; index < expression.length(); index++) {
		
		if (expression[index] == ' ') {
			
			continue;
		
		// 若不是空格则追加	
		} else {
			
			result += expression[index];
		}
	}
	
	return result;
}

Token get_token(String expression) {
	
	Token result;
	
	String buffer_token;
	
	
	for (___uint32 index = 0; index < expression.length(); index++) {
		
		buffer_token = "";
		
		// 数字 
		if (is_digit(expression[index])) {
			
			while (is_digit(expression[index])) {
				
				buffer_token += expression[index], index++;
			}
			index--;
			
			result.push_back(buffer_token);
		
		// 符号 
		} else if (is_operator(expression[index])) {
			
			// 如果有两个符号,则认定为 二元运算 和 一元运算
			// 例 37*-92
			// 则 |37|*|-92| 
			if (is_operator(expression[index + 1]) and is_digit(expression[index + 2])) {
				
				buffer_token += expression[index], index++;
				result.push_back(buffer_token), buffer_token = "";
				
				buffer_token += expression[index], index++;
				
				while (is_digit(expression[index])) {
					
					buffer_token += expression[index], index++;
				}
				index--;
				
				result.push_back(buffer_token);
			
			// 如果只有一个符号,则认为是 二元运算
			// 例 38*23
			// 则 |38|*|23|	
			} else {
				
				buffer_token += expression[index];
				
				result.push_back(buffer_token);
			}
		}
	}
	
	return result;
}

template<typename typex> typex string_to_typex(String string) {
	
	Convert convert;
	
	typex value;
	
	
	convert << string, convert >> value;
	
	return value;
}

Token operation(Token tokens) {
	
	//
	
	
	// 先扒拉乘除 
	for (Token::iterator iter = tokens.begin(); iter != tokens.end(); iter++) {
		
		if (*iter == "*") {
			
			// 左值,右值,总值 
			___sint32 left = 0, right = 0, ret = 0;
			
			
			// 左值 
			left = string_to_typex<___sint32>(*(iter - 1));
			// 右值 
			right = string_to_typex<___sint32>(*(iter + 1));
			// 总值 
			ret = left * right;
			
			// 把不要的都扔了
			// S								|23|*|89|
			//									    ↑ 
			// iter = tokens.erase(iter - 1);	|*|89|
			//									 ↑ 
			// iter = tokens.erase(iter);		|89|
			//									 ↑ 
			// *iter = std::to_string(ret);		|2047|
			//									 ↑ 
			iter = tokens.erase(iter - 1);
			iter = tokens.erase(iter);
			*iter = std::to_string(ret);
			
		} else if (*iter == "/") {
			
			___sint32 left = 0, right = 0, ret = 0;
			
			
			left = string_to_typex<___sint32>(*(iter - 1));
			right = string_to_typex<___sint32>(*(iter + 1));
			ret = left / right;
			
			iter = tokens.erase(iter - 1);
			iter = tokens.erase(iter);
			*iter = std::to_string(ret);
		}
	}
	
	// 再扒拉加减 
	for (Token::iterator iter = tokens.begin(); iter != tokens.end(); iter++) {
		
		if (*iter == "+") {
			
			___sint32 left = 0, right = 0, ret = 0;
			
			
			left = string_to_typex<___sint32>(*(iter - 1));
			right = string_to_typex<___sint32>(*(iter + 1));
			ret = left + right;
			
			iter = tokens.erase(iter - 1);
			iter = tokens.erase(iter);
			*iter = std::to_string(ret);
			
		} else if (*iter == "-") {
			
			___sint32 left = 0, right = 0, ret = 0;
			
			
			left = string_to_typex<___sint32>(*(iter - 1));
			right = string_to_typex<___sint32>(*(iter + 1));
			ret = left - right;
			
			iter = tokens.erase(iter - 1);
			iter = tokens.erase(iter);
			*iter = std::to_string(ret);
		}
	}
	
	return tokens;
}

使用方法:复制既食

GCC C++11,亲测成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值