Skip to content

Instantly share code, notes, and snippets.

@komasaru
Created October 12, 2020 01:28
Show Gist options
  • Save komasaru/074b850f4f435813c1daadfc171ab4b8 to your computer and use it in GitHub Desktop.
Save komasaru/074b850f4f435813c1daadfc171ab4b8 to your computer and use it in GitHub Desktop.
C++ source code to calculate a formula expressed with RPN.
/***************************************************************
Caculate a formula string by RPN.
DATE AUTHOR VERSION
2020.10.07 mk-mode.com 1.00 新規作成
Copyright(C) 2020 mk-mode.com All Rights Reserved.
***************************************************************/
#include <iostream> // for cout
#include <regex> // for regex_search.
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
namespace my_lib {
class Rpn {
std::string rpn; // RPN 文字列
std::vector<std::string> str2ary(std::string); // 文字列の配列化
public:
Rpn(std::string rpn) : rpn(rpn) {} // コンストラクタ
double calc(); // 計算
};
/*
* RPN による計算
*
* @return 計算結果(double)
*/
double Rpn::calc() {
std::stack<double> st; // 作業用スタック
std::regex re_0("[=\\s]+$"); // 正規表現(末尾の=とスペース)
std::regex re_1("\\s+"); // 正規表現(スペース)
std::regex re_d("\\d+"); // 正規表現(数字)
std::regex re_pl("\\+"); // 正規表現(+)
std::regex re_mn("\\-"); // 正規表現(-)
std::regex re_pr("\\*"); // 正規表現(*)
std::regex re_dv("\\/"); // 正規表現(/)
std::smatch sm; // 正規表現(マッチ部分)
double l; // オペランド(左)
double r; // オペランド(右)
double ans; // 計算結果
try {
for (std::string t : str2ary(rpn)) {
if (std::regex_search(t, sm, re_d)) {
st.push(stod(t));
continue;
}
r = st.top();
st.pop();
l = st.top();
st.pop();
if (std::regex_search(t, sm, re_pl)) {
st.push(l + r);
} else if (std::regex_search(t, sm, re_mn)) {
st.push(l - r);
} else if (std::regex_search(t, sm, re_pr)) {
st.push(l * r);
} else if (std::regex_search(t, sm, re_dv)) {
st.push(l / r);
}
}
ans = st.top();
} catch (...) {
return 0.0; // 変換失敗
}
return ans;
}
/**
* @brief RPN 文字列の配列化
*
* @param[ref] RPN 文字列 rpn (string)
* @return 配列(vector)
*/
std::vector<std::string> Rpn::str2ary(std::string rpn) {
std::vector<std::string> v;
std::regex re_0("([=\\s]+$)"); // 正規表現(末尾の=とスペース)
std::regex re_1("([0-9\\.]+|[()*/+\\-])");
std::string fmt = "";
std::smatch sm;
try {
rpn = std::regex_replace(rpn, re_0, fmt);
while (std::regex_search(rpn, sm, re_1)) {
v.push_back(sm[1].str());
rpn = sm.suffix();
}
} catch (...) {
return {}; // 配列化失敗
}
return v; // 配列化成功
}
} // namespace my_lib
int main(int argc, char* argv[]) {
std::string buf;
try {
std::cout << "? ";
getline(std::cin, buf);
if (buf.empty()) return EXIT_SUCCESS;
my_lib::Rpn r(buf);
std::cout << r.calc() << std::endl;
} catch (...) {
std::cerr << "EXCEPTION!" << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment