C++简易计算器无法计算5+10等表达式,求技术协助
问题描述
我是编程新手,编写了一款支持+、-、*、/运算的C++简易计算器。程序能够正常启动运行,但无法完成预期的计算任务,例如输入5+10无法得到正确结果15。我反复检查代码后仍未定位到问题,恳请各位提供技术帮助。以下是我的代码:
#ifndef H112 #define H112 020215L #include<iostream> #include<iomanip> #include<fstream> #include<sstream> #include<cmath> #include<cstdlib> #include<string> #include<list> #include <forward_list> #include<vector> #include<unordered_map> #include<algorithm> #include <array> #include <regex> #include<random> #include<stdexcept> //------------------------------------------------------------------------------ #if __GNUC__ && __GNUC__ < 5 inline std:: ios_base& defaultfloat(std:: ios_base& b) { b.setf(std:: ios_base::fmtflags(0), std:: ios_base::floatfield); return b; } #endif //------------------------------------------------------------------------------ using Unicode = long; //------------------------------------------------------------------------------ using namespace std; template<class T> string to_string(const T& t) { ostringstream os; os << t; return os.str(); } struct Range_error : out_of_range { // enhanced vector range error reporting int index; Range_error(int i) :out_of_range("Range error: "+to_string(i)), index(i) { } }; // trivially range-checked vector (no iterator checking): template< class T> struct Vector : public std::vector<T> { using size_type = typename std::vector<T>::size_type; #ifdef _MSC_VER // microsoft doesn't yet support C++11 inheriting constructors Vector() { } explicit Vector(size_type n) :std::vector<T>(n) {} Vector(size_type n, const T& v) :std::vector<T>(n,v) {} template <class I> Vector(I first, I last) : std::vector<T>(first, last) {} Vector(initializer_list<T> list) : std::vector<T>(list) {} #else using std::vector<T>::vector; // inheriting constructor #endif T& operator[](unsigned int i) // rather than return at(i); { if (i<0||this->size()<=i) throw Range_error(i); return std::vector<T>::operator[](i); } const T& operator[](unsigned int i) const { if (i<0||this->size()<=i) throw Range_error(i); return std::vector<T>::operator[](i); } }; // disgusting macro hack to get a range checked vector: #define vector Vector // trivially range-checked string (no iterator checking): struct String : std::string { using size_type = std::string::size_type; // using string::string; char& operator[](unsigned int i) // rather than return at(i); { if (i<0||size()<=i) throw Range_error(i); return std::string::operator[](i); } const char& operator[](unsigned int i) const { if (i<0||size()<=i) throw Range_error(i); return std::string::operator[](i); } }; namespace std { template<> struct hash<String> { size_t operator()(const String& s) const { return hash<std::string>()(s); } }; } // of namespace std struct Exit : runtime_error { Exit(): runtime_error("Exit") {} }; // error() simply disguises throws: inline void error(const string& s) { throw runtime_error(s); } inline void error(const string& s, const string& s2) { error(s+s2); } inline void error(const string& s, int i) { ostringstream os; os << s <<": " << i; error(os.str()); } template<class T> char* as_bytes(T& i) // needed for binary I/O { void* addr = &i; // get the address of the first byte // of memory used to store the object return static_cast<char*>(addr); // treat that memory as bytes } inline void keep_window_open() { cin.clear(); cout << "Please enter a character to exit\n"; char ch; cin >> ch; return; } inline void keep_window_open(string s) { if (s=="") return; cin.clear(); cin.ignore(120,'\n'); for (;;) { cout << "Please enter " << s << " to exit\n"; string ss; while (cin >> ss && ss!=s) cout << "Please enter " << s << " to exit\n"; return; } } // error function to be used (only) until error() is introduced in Chapter 5: inline void simple_error(string s) // write ``error: s and exit program { cerr << "error: " << s << '\n'; keep_window_open(); // for some Windows environments exit(1); } // make std::min() and std::max() accessible on systems with antisocial macros: #undef min #undef max // run-time checked narrowing cast (type conversion). See ???. template<class R, class A> R narrow_cast(const A& a) { R r = R(a); if (A(r)!=a) error(string("info loss")); return r; } // random number generators. See 24.7. default_random_engine& get_rand() { static default_random_engine ran; return ran; }; void seed_randint(int s) { get_rand().seed(s); } inline int randint(int min, int max) { return uniform_int_distribution<> {min, max}(get_rand()); } inline int randint(int max) { return randint(0, max); } //inline double sqrt(int x) { return sqrt(double(x)); } // to match C++0x // container algorithms. See 21.9. template<typename C> using Value_type = typename C::value_type; template<typename C> using Iterator = typename C::iterator; template<typename C> // requires Container<C>() void sort(C& c) { std::sort(c.begin(), c.end()); } template<typename C, typename Pred> // requires Container<C>() && Binary_Predicate<Value_type<C>>() void sort(C& c, Pred p) { std::sort(c.begin(), c.end(), p); } template<typename C, typename Val> // requires Container<C>() && Equality_comparable<C,Val>() Iterator<C> find(C& c, Val v) { return std::find(c.begin(), c.end(), v); } template<typename C, typename Pred> // requires Container<C>() && Predicate<Pred,Value_type<C>>() Iterator<C> find_if(C& c, Pred p) { return std::find_if(c.begin(), c.end(), p); } #endif //H112 int main() { cout<< "please enter expression(+,-,*,/):"; int lval=0; int rval; char op; cin>> lval; if (!cin) error ("no first operand"); while (cin>>op) { cin>>rval; if(!cin) error("no 2nd operand"); switch (op){ case '+': lval += rval; break; case '-': lval-=rval; break; case '*': lval*= rval; break; case '/': lval/=rval; break; default: cout<<"result:"<<lval<<'\n'; keep_window_open(); return 0; } } error("bad expression"); }
问题分析与解决
你的计算器逻辑存在一个关键问题:程序只有在遇到非+、-、*、/的字符时才会输出结果,但当你输入5+10并按下回车后,输入流中没有额外的终止字符,循环会在处理完+10后尝试继续读取下一个操作符,此时cin>>op会失败(因为输入已经结束),程序会直接走到error("bad expression"),导致无法输出计算结果。
修复方案
有两种简单的修复方式:
方式一:添加终止符(推荐)
修改程序提示,让用户输入表达式后加上一个终止符(比如=),同时在switch中添加对应分支:
int main() { cout<< "please enter expression(+,-,*,/) followed by '=' to get result:"; int lval=0; int rval; char op; cin>> lval; if (!cin) error ("no first operand"); while (cin>>op) { if (op == '=') { // 匹配终止符,输出结果 cout<<"result:"<<lval<<'\n'; keep_window_open(); return 0; } cin>>rval; if(!cin) error("no 2nd operand"); switch (op){ case '+': lval += rval; break; case '-': lval-=rval; break; case '*': lval*= rval; break; case '/': lval/=rval; break; default: error("invalid operator"); } } error("bad expression"); }
此时用户输入5+10=就能得到正确的15。
方式二:处理输入结束的情况
如果不想用终止符,可以在循环退出后判断是否已经进行过有效计算,然后输出结果:
int main() { cout<< "please enter expression(+,-,*,/):"; int lval=0; int rval; char op; bool has_calculated = false; cin>> lval; if (!cin) error ("no first operand"); while (cin>>op) { has_calculated = true; cin>>rval; if(!cin) error("no 2nd operand"); switch (op){ case '+': lval += rval; break; case '-': lval-=rval; break; case '*': lval*= rval; break; case '/': lval/=rval; break; default: cout<<"result:"<<lval<<'\n'; keep_window_open(); return 0; } } if (has_calculated) { // 如果进行过计算,输出结果 cout<<"result:"<<lval<<'\n'; keep_window_open(); return 0; } error("bad expression"); }
这样用户输入5+10并回车后,程序会输出结果15,而不是报错。
另外注意,你的代码中包含了大量和计算器功能无关的工具类(比如Vector、String、随机数生成等),可以考虑删除这些无关代码,让程序更简洁。
内容的提问来源于stack exchange,提问作者Kim Minji
相关产品推荐
相关产品推荐

