Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //main.cpp
- #include <iostream>
- #include "Vichislitel.h"
- using namespace std;
- int main(){
- Vichislitel v;
- cout<<v.Parse("(10+5)*2+2^(2+1)")<<endl;
- cout<<endl<<endl;
- system("pause");
- return 0;
- }
- //*.h
- #pragma once
- #include <vector>
- #include <string>
- class Vichislitel
- {
- public:
- Vichislitel();
- int Parse(std::string str);
- private:
- enum class unit_type{null,chislo,obyedinit,plus,minus,umnozit,delit,stepen,l_skobka,r_skobka};
- class unit{
- public:
- unit(unit_type type, int value);
- unit_type type;
- int prioritet; //0=max prioritet
- int Result(int left, int right);
- int value;
- int Stepen(int base, int stepen);
- };
- std::vector <unit> virazenie;
- int Vichislit(std::vector<unit>* units, int start_pos, int end_pos);
- int GetLeftPos(int start_pos);//Берёт первое число слева
- int GetRightPos(int start_pos);
- bool IsNumber(char c);
- int Number (char c);
- };
- //*.cpp
- #include "Vichislitel.h"
- Vichislitel::Vichislitel(){;}
- Vichislitel::unit::unit(Vichislitel::unit_type type, int value){
- unit::type = type;
- unit::value = value;
- if (type == unit_type::l_skobka) prioritet = 0;
- if (type == unit_type::r_skobka) prioritet = 0;
- if (type == unit_type::chislo) prioritet = 1;
- if (type == unit_type::obyedinit) prioritet = 2;
- if (type == unit_type::delit) prioritet = 3;
- if (type == unit_type::umnozit) prioritet = 3;
- if (type == unit_type::stepen) prioritet = 4;
- if (type == unit_type::plus) prioritet = 5;
- if (type == unit_type::minus) prioritet = 5;
- if (type == unit_type::null) prioritet = 6;
- return;
- }
- int Vichislitel::unit::Result(int left, int right){
- if (type==unit_type::null) {
- return -666;
- }
- if (type==unit_type::chislo) return value;
- if (type==unit_type::plus) return left+right;
- if (type==unit_type::minus) return left-right;
- if (type==unit_type::umnozit) return left*right;
- if (type==unit_type::delit) return left/right;
- if (type==unit_type::obyedinit){
- int right_digits = 1;
- while (right>=Stepen(10, right_digits)) right_digits++;
- return left*Stepen(10, right_digits)+right;
- }
- if (type==unit_type::stepen) return Stepen(left,right);
- return -666;
- }
- int Vichislitel::Vichislit(std::vector<unit>* units, int start_pos, int end_pos){
- //Избавляемся от скобок
- //Если видим открывающую скобку-считаем выражение до закрывающей
- //и ложим результат вместо открывающей собки, удаляя всё что в скобках
- bool is_skobki;
- do { //Ищем открывающую скобку, а за ней закрывающую
- //Важно, между ними никаких скобок
- is_skobki = false;
- int l_skobka_pos = 0;
- int r_skobka_pos = units->size()-1;
- for (int pos=start_pos; pos<=end_pos; pos++){
- if ((*units)[pos].type == unit_type::l_skobka) {
- is_skobki = true;
- l_skobka_pos = pos;
- }
- if ((*units)[pos].type == unit_type::r_skobka) {
- is_skobki = true;
- r_skobka_pos = pos;
- break;
- }
- }
- //Тут мы имеем позиции левых и правых скобок (если есть)
- if (is_skobki){
- int result = Vichislit(units, l_skobka_pos+1, r_skobka_pos-1);
- for (int pos = l_skobka_pos; pos<=r_skobka_pos; pos++){
- (*units)[pos].type=unit_type::null;
- (*units)[pos].prioritet=-1;
- }
- (*units)[l_skobka_pos].type = unit_type::chislo;
- (*units)[l_skobka_pos].value = result;
- }
- } while (is_skobki);
- //Так, теперь надо вычислить без скобок, согласно приоритетам
- for (int prioritet = 2; prioritet<= 5; prioritet++){
- for (int pos = start_pos+1; pos<end_pos; pos++){
- if ((*units)[pos].prioritet == prioritet){
- int left_pos = GetLeftPos(pos);
- int right_pos = GetRightPos(pos);
- int result = (*units)[pos].Result((*units)[left_pos].value, (*units)[right_pos].value);
- (*units)[left_pos].type = unit_type::null;
- (*units)[right_pos].type = unit_type::null;
- (*units)[pos].type = unit_type::chislo;
- (*units)[pos].value = result;
- (*units)[pos].prioritet = -1;
- }
- }
- }
- //Тут у нас должно остатся одно единственное число из всех юнитов
- for (int pos = start_pos; pos<=end_pos; pos++){
- if ((*units)[pos].type == unit_type::chislo) return (*units)[pos].value;
- }
- //Тут мы по идее не должны быть
- return -666;
- }
- int Vichislitel::GetLeftPos(int start_pos){
- for (int pos = start_pos-1; pos>=0; pos--){
- if (virazenie[pos].type == unit_type::chislo) return pos;
- }
- return -1;
- }
- int Vichislitel::GetRightPos(int start_pos){
- for (int pos = start_pos+1; pos<virazenie.size(); pos++){
- if (virazenie[pos].type == unit_type::chislo) return pos;
- }
- return -1;
- }
- int Vichislitel::unit::Stepen(int base, int stepen){
- int result = 1;
- for (int i=0; i<stepen; i++) result *= base;
- return result;
- }
- int Vichislitel::Parse(std::string str){
- virazenie.clear();
- for (int pos=0; pos<str.size(); pos++){
- if (str[pos] == '(')virazenie.push_back(unit(unit_type::l_skobka, 0));
- if (str[pos] == ')')virazenie.push_back(unit(unit_type::r_skobka, 0));
- if (IsNumber(str[pos])){
- virazenie.push_back(unit(unit_type::chislo, Number(str[pos])));
- if (pos<str.size()-1){
- if (IsNumber(str[pos+1])){
- virazenie.push_back(unit(unit_type::obyedinit, 0));
- }
- }
- }
- if (str[pos] == '+')virazenie.push_back(unit(unit_type::plus, 0));
- if (str[pos] == '-')virazenie.push_back(unit(unit_type::minus, 0));
- if (str[pos] == '*')virazenie.push_back(unit(unit_type::umnozit, 0));
- if (str[pos] == '/')virazenie.push_back(unit(unit_type::delit, 0));
- if (str[pos] == '^')virazenie.push_back(unit(unit_type::stepen, 0));
- }
- return Vichislit(&virazenie, 0, virazenie.size()-1);
- }
- int Vichislitel::Number(char c){
- if (c == '0') return 0;
- if (c == '1') return 1;
- if (c == '2') return 2;
- if (c == '3') return 3;
- if (c == '4') return 4;
- if (c == '5') return 5;
- if (c == '6') return 6;
- if (c == '7') return 7;
- if (c == '8') return 8;
- if (c == '9') return 9;
- return -1;
- }
- bool Vichislitel::IsNumber(char c){
- if (Number(c) != -1) return true;
- return false;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement