Advertisement
Guest User

Код разработчика

a guest
Dec 16th, 2013
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.96 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <iostream>
  4. #include <string>
  5. #include <vector>
  6. #include <stdexcept>
  7.  
  8. struct token {
  9.     enum { E_UNDEF, E_NUMBER, E_OPERATOR, E_LEVEL  } type;
  10.  
  11.     union {
  12.         double d_val;
  13.         int i_val;
  14.         char c_val;
  15.     } data;
  16.  
  17.     token() {
  18.         type = E_UNDEF;
  19.     }
  20.  
  21.     token(double val) : type(E_NUMBER) {
  22.         data.d_val = val;
  23.     }
  24.     token(int val) : type(E_LEVEL) {
  25.         data.i_val = val;
  26.     }
  27.     token(char val) : type(E_OPERATOR) {
  28.         data.c_val = val;
  29.     }
  30. };
  31.  
  32. typedef std::vector<token> tokens;
  33.  
  34. void push_level(tokens &pr, int level) {
  35.     if (pr.empty() || pr.back().type != token::E_LEVEL) {
  36.         pr.push_back(token(level));
  37.     } else {
  38.         pr.back().data.i_val += level;
  39.     }
  40. }
  41.  
  42. void push_operator(tokens &pr, char op) {
  43.     pr.push_back(token(op));
  44. }
  45.  
  46. void push_number(tokens &pr, int num) {
  47.     if (pr.empty() || pr.back().type == token::E_LEVEL || (pr.back().type == token::E_OPERATOR && pr.size() > 1 && pr[pr.size() - 2].type == token::E_NUMBER) ) {
  48.         pr.push_back(token((double)num));
  49.     } else if (pr.back().type == token::E_OPERATOR && (pr.size() == 1 || pr[pr.size() - 2].type == token::E_LEVEL) ) {
  50.         if (pr.back().data.c_val == '*' || pr.back().data.c_val == '/') {
  51.             throw std::domain_error("unexpected operator");
  52.         }
  53.         if (pr.back().data.c_val == '-') {
  54.             num = -num;
  55.         }
  56.         pr.pop_back();
  57.         pr.push_back(token((double)num));
  58.     } else {
  59.         throw std::domain_error("unexpected number");
  60.     }
  61. }
  62.  
  63. void pop_level(tokens &pr, int level) {
  64.     if (level <= 0) {
  65.         return;
  66.     }
  67.     if (pr.empty() || pr.back().type == token::E_LEVEL || pr.back().type == token::E_OPERATOR) {
  68.         throw std::domain_error("unexpected closing brace");
  69.     } else if (pr.size() > 1 && pr[pr.size() - 2].type == token::E_LEVEL) {
  70.         if (pr[pr.size() - 2].data.i_val > level) {
  71.             pr[pr.size() - 2].data.i_val -= level;
  72.         } else {
  73.             int delta = level - pr[pr.size() - 2].data.i_val;
  74.             token tmp = pr.back();
  75.             pr.pop_back(); pr.pop_back();
  76.             pr.push_back(tmp);
  77.             pop_level(pr, delta);
  78.         }
  79.     } else if (pr.size() > 3) {
  80.         token s2 = pr.back(); pr.pop_back();
  81.         token op = pr.back(); pr.pop_back();
  82.         token s1 = pr.back(); pr.pop_back();
  83.  
  84.         if (s1.type != token::E_NUMBER || op.type != token::E_OPERATOR || s2.type != token::E_NUMBER) {
  85.             throw std::domain_error("unexpected closing brace");
  86.         }
  87.  
  88.         switch (op.data.c_val) {
  89.             case '+':
  90.                 s1.data.d_val += s2.data.d_val;
  91.                 break;
  92.             case '-':
  93.                 s1.data.d_val -= s2.data.d_val;
  94.                 break;
  95.             case '*':
  96.                 s1.data.d_val *= s2.data.d_val;
  97.                 break;
  98.             case '/':
  99.                 s1.data.d_val /= s2.data.d_val;
  100.                 break;
  101.             default:
  102.             throw std::domain_error("internal error");
  103.         }
  104.  
  105.         if (pr.back().type == token::E_LEVEL) {
  106.             if (pr.back().data.i_val > level) {
  107.                 pr.back().data.i_val -= level;
  108.                 pr.push_back(s1);
  109.             } else {
  110.                 int delta = level - pr.back().data.i_val;
  111.                 pr.pop_back();
  112.                 pr.push_back(s1);
  113.                 pop_level(pr, delta);
  114.             }
  115.         } else if (pr.back().type == token::E_OPERATOR) {
  116.             pr.push_back(s1);
  117.             pop_level(pr, level);
  118.         } else {
  119.             throw std::domain_error("unexpected closing brace");
  120.         }
  121.     } else {
  122.         throw std::domain_error("unexpected closing brace");
  123.     }
  124. }
  125.  
  126. double process(const std::string &str) {
  127.     tokens program;
  128.  
  129.     push_level(program, 3);
  130.     for (std::string::const_iterator cit = str.begin(); cit != str.end(); ++cit) {
  131.         switch (*cit) {
  132.             case '(':
  133.                 push_level(program, 3);
  134.                 break;
  135.             case ')':
  136.                 pop_level(program, 3);
  137.                 break;
  138.             case '*':
  139.             case '/':
  140.                 pop_level(program, 1);
  141.                 push_operator(program, *cit);
  142.                 push_level(program, 1);
  143.                 break;
  144.             case '+':
  145.             case '-':
  146.                 if (cit == str.begin() || strchr("(+/-*", *(cit-1))) {
  147.                     push_operator(program, *cit);
  148.                 } else {
  149.                     pop_level(program, 2);
  150.                     push_operator(program, *cit);
  151.                     push_level(program, 2);
  152.                 }
  153.                 break;
  154.             case ' ':
  155.                 break;
  156.             case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
  157.                 {
  158.                     int curnum = 0;
  159.                     while (cit != str.end()) {
  160.                         curnum = 10*curnum + (*cit - '0');
  161.                         if ((cit + 1) == str.end() || !isdigit(*(cit+1))) {
  162.                             break;
  163.                         }
  164.                         ++cit;
  165.                     }
  166.                     push_number(program, curnum);
  167.                 }
  168.                 break;
  169.             default:
  170.                 throw std::domain_error("unexpected symbol");
  171.         }
  172.     }
  173.     pop_level(program, 3);
  174.  
  175.     if (program.size() == 0 || program.size() > 1) {
  176.         throw std::domain_error("incomplete expression");
  177.     }
  178.  
  179.     return program.back().data.d_val;
  180. }
  181.  
  182. int main() {
  183.     std::string line;
  184.     while (!std::cin.eof()) {
  185.         std::getline(std::cin, line);
  186.  
  187.         if (line.length() > 0) {
  188.             try {
  189.                 std::cout << process(line) << std::endl;
  190.             } catch (std::exception &e) {
  191.                 std::cout << "error: " << e.what() << std::endl;
  192.             }
  193.         }
  194.     }
  195.  
  196.     return 0;
  197. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement