Advertisement
nefton

Untitled

Oct 26th, 2020
2,811
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //main.cpp
  2. #include <iostream>
  3. #include "Vichislitel.h"
  4.  
  5.  
  6. using namespace std;
  7.  
  8. int main(){
  9.  
  10.     Vichislitel v;
  11.    
  12.     cout<<v.Parse("(10+5)*2+2^(2+1)")<<endl;
  13.  
  14.     cout<<endl<<endl;
  15.     system("pause");
  16.  
  17.     return 0;
  18. }
  19.  
  20. //*.h
  21. #pragma once
  22.  
  23. #include <vector>
  24. #include <string>
  25.  
  26. class Vichislitel
  27. {
  28. public:
  29.     Vichislitel();
  30.     int Parse(std::string str);
  31.  
  32. private:
  33.     enum class unit_type{null,chislo,obyedinit,plus,minus,umnozit,delit,stepen,l_skobka,r_skobka};
  34.     class unit{
  35.     public:
  36.         unit(unit_type type, int value);
  37.         unit_type type;
  38.         int prioritet; //0=max prioritet
  39.         int Result(int left, int right);
  40.         int value;
  41.         int Stepen(int base, int stepen);
  42.     };
  43.     std::vector <unit> virazenie;
  44.    
  45.     int Vichislit(std::vector<unit>* units, int start_pos, int end_pos);
  46.  
  47.     int GetLeftPos(int start_pos);//Берёт первое число слева
  48.     int GetRightPos(int start_pos);
  49.     bool IsNumber(char c);
  50.     int Number (char c);
  51. };
  52.  
  53. //*.cpp
  54. #include "Vichislitel.h"
  55.  
  56.  
  57. Vichislitel::Vichislitel(){;}
  58.  
  59.  
  60. Vichislitel::unit::unit(Vichislitel::unit_type type, int value){
  61.     unit::type = type;
  62.     unit::value = value;
  63.     if (type == unit_type::l_skobka) prioritet = 0;
  64.     if (type == unit_type::r_skobka) prioritet = 0;
  65.     if (type == unit_type::chislo) prioritet = 1;
  66.     if (type == unit_type::obyedinit) prioritet = 2;
  67.     if (type == unit_type::delit) prioritet = 3;
  68.     if (type == unit_type::umnozit) prioritet = 3;
  69.     if (type == unit_type::stepen) prioritet = 4;
  70.     if (type == unit_type::plus) prioritet = 5;
  71.     if (type == unit_type::minus) prioritet = 5;
  72.     if (type == unit_type::null) prioritet = 6;
  73.     return;
  74. }
  75.  
  76.  
  77.  
  78. int Vichislitel::unit::Result(int left, int right){
  79.    
  80.     if (type==unit_type::null) {
  81.         return -666;
  82.     }
  83.    
  84.     if (type==unit_type::chislo) return value;
  85.     if (type==unit_type::plus) return left+right;
  86.     if (type==unit_type::minus) return left-right;
  87.     if (type==unit_type::umnozit) return left*right;
  88.     if (type==unit_type::delit) return left/right;
  89.  
  90.     if (type==unit_type::obyedinit){
  91.         int right_digits = 1;
  92.         while (right>=Stepen(10, right_digits)) right_digits++;
  93.         return left*Stepen(10, right_digits)+right;
  94.     }
  95.     if (type==unit_type::stepen) return Stepen(left,right);
  96.  
  97.  
  98.     return -666;
  99. }
  100.  
  101. int Vichislitel::Vichislit(std::vector<unit>* units, int start_pos, int end_pos){
  102.    
  103.     //Избавляемся от скобок
  104.     //Если видим открывающую скобку-считаем выражение до закрывающей
  105.     //и ложим результат вместо открывающей собки, удаляя всё что в скобках
  106.     bool is_skobki;
  107.     do { //Ищем открывающую скобку, а за ней закрывающую
  108.         //Важно, между ними никаких скобок
  109.         is_skobki = false;
  110.         int l_skobka_pos = 0;
  111.         int r_skobka_pos = units->size()-1;
  112.  
  113.         for (int pos=start_pos; pos<=end_pos; pos++){
  114.                 if ((*units)[pos].type == unit_type::l_skobka) {
  115.                     is_skobki = true;
  116.                     l_skobka_pos = pos;
  117.                 }
  118.                 if ((*units)[pos].type == unit_type::r_skobka) {
  119.                     is_skobki = true;
  120.                     r_skobka_pos = pos;
  121.                     break;
  122.                 }
  123.         }
  124.         //Тут мы имеем позиции левых и правых скобок (если есть)
  125.         if (is_skobki){
  126.             int result = Vichislit(units, l_skobka_pos+1, r_skobka_pos-1);
  127.             for (int pos = l_skobka_pos; pos<=r_skobka_pos; pos++){
  128.                 (*units)[pos].type=unit_type::null;
  129.                 (*units)[pos].prioritet=-1;
  130.             }
  131.             (*units)[l_skobka_pos].type = unit_type::chislo;
  132.             (*units)[l_skobka_pos].value = result;
  133.         }
  134.     } while (is_skobki);
  135.     //Так, теперь надо вычислить без скобок, согласно приоритетам
  136.  
  137.     for (int prioritet = 2; prioritet<= 5; prioritet++){
  138.         for (int pos = start_pos+1; pos<end_pos; pos++){
  139.             if ((*units)[pos].prioritet == prioritet){
  140.                 int left_pos = GetLeftPos(pos);
  141.                 int right_pos = GetRightPos(pos);
  142.                 int result = (*units)[pos].Result((*units)[left_pos].value, (*units)[right_pos].value);
  143.                 (*units)[left_pos].type = unit_type::null;
  144.                 (*units)[right_pos].type = unit_type::null;
  145.                 (*units)[pos].type = unit_type::chislo;
  146.                 (*units)[pos].value = result;
  147.                 (*units)[pos].prioritet = -1;
  148.             }
  149.         }
  150.     }
  151.     //Тут у нас должно остатся одно единственное число из всех юнитов
  152.  
  153.     for (int pos = start_pos; pos<=end_pos; pos++){
  154.         if ((*units)[pos].type == unit_type::chislo) return (*units)[pos].value;
  155.     }
  156.  
  157.     //Тут мы по идее не должны быть
  158.     return -666;
  159. }
  160.  
  161. int Vichislitel::GetLeftPos(int start_pos){
  162.     for (int pos = start_pos-1; pos>=0; pos--){
  163.         if (virazenie[pos].type == unit_type::chislo) return pos;
  164.     }
  165.     return -1;
  166. }
  167.  
  168. int Vichislitel::GetRightPos(int start_pos){
  169.     for (int pos = start_pos+1; pos<virazenie.size(); pos++){
  170.         if (virazenie[pos].type == unit_type::chislo) return pos;
  171.     }
  172.     return -1;
  173. }
  174.  
  175.  
  176. int Vichislitel::unit::Stepen(int base, int stepen){
  177.     int result = 1;
  178.     for (int i=0; i<stepen; i++) result *= base;
  179.     return result;
  180. }
  181.  
  182. int Vichislitel::Parse(std::string str){
  183.  
  184.     virazenie.clear();
  185.     for (int pos=0; pos<str.size(); pos++){
  186.         if (str[pos] == '(')virazenie.push_back(unit(unit_type::l_skobka, 0));
  187.         if (str[pos] == ')')virazenie.push_back(unit(unit_type::r_skobka, 0));
  188.         if (IsNumber(str[pos])){
  189.             virazenie.push_back(unit(unit_type::chislo, Number(str[pos])));
  190.             if (pos<str.size()-1){
  191.                 if (IsNumber(str[pos+1])){
  192.                     virazenie.push_back(unit(unit_type::obyedinit, 0));
  193.                 }
  194.             }
  195.         }
  196.         if (str[pos] == '+')virazenie.push_back(unit(unit_type::plus, 0));
  197.         if (str[pos] == '-')virazenie.push_back(unit(unit_type::minus, 0));
  198.         if (str[pos] == '*')virazenie.push_back(unit(unit_type::umnozit, 0));
  199.         if (str[pos] == '/')virazenie.push_back(unit(unit_type::delit, 0));
  200.         if (str[pos] == '^')virazenie.push_back(unit(unit_type::stepen, 0));
  201.     }
  202.  
  203.     return Vichislit(&virazenie, 0, virazenie.size()-1);
  204. }
  205.  
  206. int Vichislitel::Number(char c){
  207.     if (c == '0') return 0;
  208.     if (c == '1') return 1;
  209.     if (c == '2') return 2;
  210.     if (c == '3') return 3;
  211.     if (c == '4') return 4;
  212.     if (c == '5') return 5;
  213.     if (c == '6') return 6;
  214.     if (c == '7') return 7;
  215.     if (c == '8') return 8;
  216.     if (c == '9') return 9;
  217.     return -1;
  218. }
  219.  
  220. bool Vichislitel::IsNumber(char c){
  221.     if (Number(c) != -1) return true;
  222.     return false;
  223. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement