首先需要下面几个函数作为工具
判断是否是数字和运算符号
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,亲测成功
|