IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++计算表达式(暂时不支持带括号运算) -> 正文阅读

[C++知识库]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,亲测成功

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-27 13:54:18  更:2021-09-27 13:56:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 4:38:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计