zoukankan      html  css  js  c++  java
  • C++实现计算器

     目标:实现一个可以计算加减乘除四种运算,可以识别处理'(',')','+','-','*','/','=',可以操作整数的计算器。

     步骤:(1)将中缀表达式转换成后缀表达式

        (2)计算后缀表达式

        (3)输出结果

     准备工作:

     1.包含头文件:

    1 #include <iostream>
    2 #include <stack>
    3 #include <string>
    4 
    5 using namespace std;

     2.定义两个栈

    1 stack<char> opt;    // 操作符栈
    2 stack<double> val;    // 操作数栈

     3.定义两个常量表示在数字中的状态

    1 const int IN = 0;    // 在数字中
    2 const int OUT = 1;    // 在数字外

     4.为操作符规定优先级,并判断输入的操作符是否合法

    1 char opt_set[10] = "+-*/()=";
     1 /* 为每一个操作符返回一个数,数越大优先级越高 */
     2 
     3 int level(char theOpt){
     4     for(int i = 0; i < 7; i++){
     5         if(theOpt == opt_set[i])
     6             return i;
     7     }
     8     return -1;
     9 }
    10 
    11 /* 判断输入的操作符是否合法 */
    12 
    13 bool in_set(char theChar){
    14     for(int i = 0; i < 7; i++){
    15         if(theChar == opt_set[i])
    16             return true;
    17     }
    18     return false;
    19 }

     5.整理输入,判断是否有非法字符,用到in_set()函数

     1 /* 用于去除空格并检查是否有非法字符 */
     2 bool del_space(string &theString){
     3     string res;
     4     for(int i = 0; i < theString.length(); i++){
     5         if(in_set(theString[i]) || isdigit(theString[i])){
     6             res += theString[i];
     7         }
     8         else if(theString[i] == ' ')
     9             ;
    10         else{
    11             cout << "表达式含有错误字符,请重新输入。" << endl;
    12             return false;
    13         }
    14     }
    15     theString = res;
    16     return true;
    17 }
    18
    6.把数字转换成字符串
    20 21 string to_string(int theInt) 22 { 23 if(theInt == 0) 24 return string("0"); 25 bool neg = false; 26 if(theInt < 0) 27 { 28 neg = true; 29 theInt = -theInt; 30 } 31 string res; 32 while(theInt != 0) 33 { 34 char c = (theInt % 10) + '0'; 35 res = c + res; 36 theInt /= 10; 37 } 38 if(neg) 39 res = '-' + res; 40 return res; 41 }

     实现第一步:将中缀表达式转化成后缀表达式

     1 /* 将中缀表达式转换成后缀表达式 */
     2 bool change(string &from, string &to){
     3     int theInt = 0;        // 暂存数字
     4     int state = OUT;     // 初始状态:在数字外
     5     char c;
     6     /*
     7     if(from[from.length() - 1] != '='){
     8         cout << "等于号语法有误!" << endl;
     9         return false;
    10     }
    11     */
    12     for(int i = 0; i < from.length(); i++){
    13         c = from[i];
    14         if(isdigit(c)){
    15             theInt *= 10;
    16             theInt += c - '0';
    17             state = IN;    // 状态:在数字内
    18         }
    19         else{
    20             if(state == IN){        // 刚刚处理了数字
    21                 to += to_string(theInt) + ' ';
    22                 theInt = 0;
    23             }
    24             if(c == '='){
    25                 /*
    26                 if(i != from.length() - 1){
    27                     cout << "等于号语法有误!" << endl;
    28                     return false;                    
    29                 }
    30                 */
    31                 break;
    32             }
    33             else if(c == '(')
    34                 opt.push(c);
    35             else if(c == ')'){
    36                 while(!opt.empty() && opt.top() != '('){
    37                     to += opt.top();
    38                     to += ' ';
    39                     opt.pop();
    40                 }
    41                 /*
    42                 if(opt.empty()){
    43                     cout << "括号匹配有误!" << endl;
    44                     return false;
    45                 }
    46                 else
    47                 */
    48                     opt.pop();
    49             }
    50             else{
    51                 while(true){
    52                     if(opt.empty() || opt.top() == '(')
    53                         opt.push(c);
    54                     else if(level(c) > level(opt.top()))
    55                         opt.push(c);
    56                     else{
    57                         to += opt.top();
    58                         to += ' ';
    59                         opt.pop();
    60                         continue;
    61                     }
    62                     break;
    63                 }
    64             }
    65             state = OUT;    // 状态:在数字外
    66         }
    67     }
    68     while(!opt.empty()){
    69         /*
    70         if(opt.top() == '('){
    71             cout << "括号匹配有误!" << endl;
    72             return false;
    73         }
    74         */
    75         to += opt.top();
    76         to += ' ';
    77         opt.pop();
    78     }
    79     return true;
    80 } 

    实现第二步:计算后缀表达式

     1 bool compute(string &theExp){
     2     int theInt = 0;        // 暂存数字
     3     int state = OUT;     // 初始状态:在数字外
     4     char c;
     5     for(int i = 0; i < theExp.length(); i++){
     6         c = theExp[i];
     7         if(isdigit(c)){
     8             theInt *= 10;
     9             theInt += c - '0';
    10             state = IN;    // 状态:在数字内
    11         }
    12         else{
    13             if(state == IN){        // 刚刚处理了数字
    14                 val.push(theInt);
    15                 theInt = 0;
    16             }
    17             double x, y;
    18             if(c != ' '){
    19                 /*
    20                 if(val.empty()){
    21                     cout << "操作数语法错误!" << endl;
    22                     return false;
    23                 }
    24                 */
    25                 x = val.top();
    26                 val.pop();
    27                 /*
    28                 if(val.empty()){
    29                     cout << "操作数语法错误!" << endl;
    30                     return false;
    31                 }
    32                 */
    33                 y = val.top();
    34                 val.pop();
    35                 switch(c){
    36                     case '+':
    37                         val.push(x + y);
    38                         break;
    39                     case '-':
    40                         val.push(y - x);
    41                         break;
    42                     case '*':
    43                         val.push(x * y);
    44                         break;
    45                     case '/':
    46                         val.push(y / x);
    47                         break;
    48                     default:
    49                         cout << "未知的错误!" << endl;
    50                 }
    51             }
    52             state = OUT;
    53         }
    54     }
    55     /*
    56     if(val.size() != 1){
    57         cout << "缺少操作符!" << endl;
    58         return false;
    59     }
    60     */
    61     return true;
    62 }

    实现第三步:测试,输出结果

     1 int main()
     2 {
     3     cout << "请保证所有的操作数均为正整数,且不要输入(+x)的形式。" << endl;
     4     cout << "若答案为小数,请按照四舍五入的规则保留小数点后三位。" << endl;
     5     while(true){
     6         // 清空流
     7         cin.clear();
     8         cin.sync();
     9         // 初始化操作:清空两个栈
    10         while(!opt.empty()){
    11             opt.pop();
    12         }
    13         while(!val.empty()){
    14             val.pop();
    15         }
    16         
    17         // 输入表达式
    18         string init_exp;
    19         cout << "请输入以'='结尾的表达式,或输入"exit"退出:";
    20         getline(cin, init_exp);
    21         
    22         if(init_exp == string("exit")){
    23             break;
    24         }
    25         
    26         // 去除空格并检查是否有非法字符
    27         if(!del_space(init_exp))
    28             continue;
    29         
    30         // 转换为后缀表达式
    31         string cng_exp;
    32         cng_exp.clear();
    33         if(!change(init_exp, cng_exp))
    34             continue;
    35         cout << "此表达式转换为后缀表达式为:" << cng_exp << endl;
    36         
    37         // 计算后缀表达式
    38         if(!compute(cng_exp))
    39             continue;
    40         
    41         double stdans = val.top();
    42         cout << "此表达式的运算结果为:" << stdans << endl;
    43     }
    44     return 0;
    45 } 

     

  • 相关阅读:
    html问题记录20180529
    html问题记录20180518
    html问题记录20180515
    Redis持久化--AOF
    Redis持久化--RDB
    Redis事件模型
    两个字符串的编辑距离-动态规划方法
    Reactor事件模型在Redis中的应用
    事件驱动模式--Reactor
    IO多路复用--总结
  • 原文地址:https://www.cnblogs.com/zyr001/p/11063875.html
Copyright © 2011-2022 走看看