⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 a_cal.cpp

📁 一个不错
💻 CPP
字号:
/* Copyright is licensed under GNU LGPL.                 by I.J.Wang 2005  Command line calculator  Read arithmetic expression from standard input and write along with the  evaluated result, to standard output.  Build: 1. decide the result type RTYPE as double, long..,etc.         2. make a_cal  Note: A small calculator program deserves reference: e-0.02718.tar.gz,        http://freshmeat.net/projects/e-expr/*/#include "../src/wy_uty.h"#include "../src/wy__rdbuf.h"#include <unistd.h>#include <limits>#include <cmath>//#define PARSE_DUMP#ifndef RTYPE#define RTYPE double#endif/* The followings are functions evaluating arithmetic expression of s   The main function is eva_expr(WyCSeg, ResType&) [Grammar] T-> T*F | T/F     ; Search for the last * or / (ignore parenthesized text)     F E-> E+T  | E-T    ; Search for the last + or - (ignore parenthesized text)     T | -T  | +T F-> D | (E)     sin(E)     cos(E)     tan(E)     asin(E)     acos(E)     atan(E)     log(E)     log10(E)     exp(E)     exp10(E)     sqrt(E)      D-> digit         ; no scientific notation (_strnum dependant)     D digit digit-> [0-9] [Ret] Ok          Result is stored in res       Wym_EBADMSG       Wym_ENOENT*/typedef RTYPE ResType;static WyRet eva_E(WyCSeg s, ResType& res);inline static bool is_digit(char ch) {  return (ch>='0')&&(ch<='9');};inline static bool is_blank(char ch) {  return (ch==' ')||(ch=='\t');};// [Syn] Scan backward from buf_s for the opening parenthesis symbol och//       in string indicated by [buf_a,buf_s]. *buf_s must be the closing//       parenthesis symbol.//// [Ret] pointer to the opening parenthesis symbol (identical to och)//       or zero if end of search.//static const char* bscan_closing(const char* buf_a,const char* buf_s,char och){ if((buf_a==NULL)||(buf_s==NULL)) {   WY_THROW( WyRet(Wym_EFAULT) ); } if(buf_a>=buf_s) {   if(buf_a==buf_s) {     return NULL;   }   WY_THROW( WyRet(Wym_EINVAL) ); } const char cch(*buf_s); int diff_cnt(1); const char* sptr(buf_s-1); for(;; --sptr) {   if(*sptr==och) {     --diff_cnt;     if(diff_cnt==0) {       return(sptr);     }   } else if(*sptr==cch) {     ++diff_cnt;   } else {     // Ignore other character   }   if(sptr==buf_a) {     return (const char*)0;   } }};static WyRet eva_F(WyCSeg s, ResType& res){#ifdef PARSE_DUMP Wy::cout << "F:" << s << '\n';#endif WyRet r; if(s.size()<=0) {   WY_RETURN( Wym_ENOENT ); } if(is_digit(s.front())) {   const char* endptr;   if((r=Wy::_strnum(res,&endptr,s,10))!=Ok) {     WY_RETURN(r);   }   return(Ok); } if(s.front()=='(') {   if(s.back()!=')') {     WY_RETURN( Wym_EBADMSG );   }   return eva_E( s.cseg(1,s.size()-2),res ); } if(s.back()!=')') {   WY_RETURN( Wym_EBADMSG ); } if(std::numeric_limits<ResType>::is_integer) { } else {   ResType tmp;   if(s.cseg(0,4)=="sin(") {     if((r=eva_E(s.cseg(4,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=std::sin(tmp);     return(Ok);   }   if(s.cseg(0,4)=="cos(") {     if((r=eva_E(s.cseg(4,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=std::cos(tmp);     return(Ok);   }   if(s.cseg(0,4)=="tan(") {     if((r=eva_E(s.cseg(4,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=std::tan(tmp);     return(Ok);   }   if(s.cseg(0,5)=="asin(") {     if((r=eva_E(s.cseg(5,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=std::asin(tmp);     return(Ok);   }   if(s.cseg(0,5)=="acos(") {     if((r=eva_E(s.cseg(5,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=std::acos(tmp);     return(Ok);   }   if(s.cseg(0,5)=="atan(") {     if((r=eva_E(s.cseg(5,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=std::atan(tmp);     return(Ok);   }   if(s.cseg(0,4)=="log(") {     if((r=eva_E(s.cseg(4,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=std::log(tmp);     return(Ok);   }   if(s.cseg(0,6)=="log10(") {     if((r=eva_E(s.cseg(6,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=std::log10(tmp);     return(Ok);   }   if(s.cseg(0,4)=="exp(") {     if((r=eva_E(s.cseg(4,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=std::exp(tmp);     return(Ok);   }   if(s.cseg(0,6)=="exp10(") {     if((r=eva_E(s.cseg(6,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=exp10(tmp);     return(Ok);   }   if(s.cseg(0,5)=="sqrt(") {     if((r=eva_E(s.cseg(5,s.size()-2),tmp))!=Ok) {       WY_RETURN(r);     }     res=std::sqrt(tmp);     return(Ok);   } } WY_RETURN( Wym_EBADMSG );};static WyRet eva_T(WyCSeg s, ResType& res){#ifdef PARSE_DUMP Wy::cout << "T:" << s << '\n';#endif if(s.size()<=0) {   WY_RETURN( Wym_ENOENT ); } const char* aptr(s.begin()); const char* zptr(s.end()); const char* sptr(zptr-1); for( ; ; --sptr) {   if((*sptr=='*')||(*sptr=='/')) { // operator */     WyRet r;     ResType res1,res2;     r=eva_T(WyCSeg(aptr,sptr),res1);     if(r!=Ok) {       WY_RETURN(r);     }     r=eva_F(WyCSeg(sptr+1,zptr),res2);     if(r!=Ok) {       WY_RETURN(r);     }     if(*sptr=='*') {       res=res1*res2;     } else {       res=res1/res2;     }     return(Ok);   }   if(*sptr==')') {     sptr=bscan_closing(aptr,sptr,'(');     if(sptr==0) {       WY_RETURN( Wym_EBADMSG );     }   }   if(sptr==aptr) {     return eva_F(WyCSeg(aptr,zptr),res);   } } // UNREACHABLE};static WyRet eva_E(WyCSeg s, ResType& res){#ifdef PARSE_DUMP Wy::cout << "E:" << s << '\n';#endif if(s.size()<=0) {   WY_RETURN( Wym_ENOENT ); } const char* aptr(s.begin()); const char* zptr(s.end()); const char* sptr(zptr-1); for( ; ; --sptr) {   if((*sptr=='-')||(*sptr=='+')) { // operator +-     WyRet r;     if(sptr==aptr) {       r=eva_T(WyCSeg(sptr+1,zptr),res);       if(r!=Ok) {         WY_RETURN(r);       }       if(*sptr=='-') {         res=-res;       }       return(Ok);     } else {       ResType res1,res2;       r=eva_E(WyCSeg(aptr,sptr),res1);       if(r!=Ok) {         WY_RETURN(r);       }       r=eva_T(WyCSeg(sptr+1,zptr),res2);       if(r!=Ok) {         WY_RETURN(r);       }       if(*sptr=='-') {         res=res1-res2;       } else {         res=res1+res2;       }       return(Ok);     }   }   if(*sptr==')') {     sptr=bscan_closing(aptr,sptr,'(');     if(sptr==0) {       WY_RETURN( Wym_EBADMSG );     }   }   if(sptr==aptr) {     return eva_T(WyCSeg(aptr,zptr),res);   } } // UNREACHABLE};WyRet eva_expr(WyCSeg s, ResType& res){ // Copy s to str and remove blanks. Call eva_E(..) with this no blank copy // of expression. // WyStr str; for(const char* aptr=s.begin(); aptr!=s.end(); ++aptr) {   if(is_blank(*aptr)==true) {     continue;   }   const WyRet r( str.append(*aptr) );   if(r!=Ok) {     WY_RETURN(r);   } } return eva_E(str.cseg(),res);};int main(int argc, char* argv[])try { static const char* cmd_syntax=               "Command line calculator\n"               " Read arithmetic expression from standard input and write,\n"               " along with the evaluated result, to standard output\n"               "Usage: $./a_cal\n"               "\n"; // Command-line options // {  const char optstr[]="h";  int optch;    while((optch=::getopt(argc,argv,optstr))!=-1) {    switch(optch) {      case 'h':	      Wy::cout << cmd_syntax;	      return(0);      case ':':     // missing parameter      case '?':     // unknown option	      Wy::cerr << "parameter error\n";	      Wy::cerr << cmd_syntax;              return(-1);      default:	      Wy::cerr << "parameter fault\n";              return(-1);    }  }  for( ; optind<argc; optind++) {    Wy::cerr << "parameter error\n";    return(-1);  } } WyRet r; Wy__RdBuf inbf(&Wy::cin); WyCSeg rseg; ResType res; for(;;) {   if((r=inbf.getdata(rseg,1024,'\n'))!=Ok) {     WY_THROW(r);   }   if(rseg.size()==0) {     return(0);   }   // not show the trailing '\n'   if(rseg.back()=='\n') {     rseg._move_end(-1);   }   if(rseg.size()==0) {     continue;     // blank line   }   Wy::cout << rseg;   if((r=eva_expr(rseg,res))!=Ok) {     Wy::cout << " --- " << Wy::wrd(r) << '\n';   } else {     Wy::cout << " = " << Wy::wrd(res) << '\n';   } } return(0);}catch(const WyRet& e) { if(e!=Ok) {   Wy::cerr << Wy::wrd(e) << '\n'; } return e->c_repcode();}catch(...) { Wy::cerr << "main caught(...)\n"; return(-1);};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -