Paste will expire never.
- #include <iostream>
- #include <string>
- #include <vector>
- #include <cmath>
- #include <algorithm>
- using namespace std;
- enum LexType {PLS,MNS,MUL,DIV,OPN,CLS,NUM,FNC,END,NAN};
- string tSymbols = "+-*/()";
- string expStr; // первоначальное арифметическое выражение
- int expPos; // текущая позиция выражения
- LexType curLex = NAN; // тип текущей лексемы
- string lexVal; // значение текущей лексемы
- const int funcCount = 2;
- string funcsName[] = {"sin","cos"};
- double (*pfunc[])(double) = {&sin, &cos};
- void input() {
- getline(cin,expStr);
- }
- bool isNum(const string &str) {
- for (int i=0;i<str.size();i++) {
- if (!isdigit(str[i]) && str[i]!='.')
- return false;
- }
- return count(str.begin(), str.end(),'.')<=1;
- }
- double toNum(string &str) {
- double res;
- sscanf(str.c_str(), "%lf", &res);
- return res;
- }
- bool isFunc(const string &str) {
- for (int i=0;i<funcCount;i++) {
- if (str == funcsName[i])
- return true;
- }
- return false;
- }
- int FuncPos(const string &str) {
- for (int i=0;i<funcCount;i++) {
- if (str == funcsName[i])
- return i;
- }
- return -1;
- }
- bool isSep(const char c) {
- return tSymbols.find(c) != -1 || c == ' ';
- }
- void nextLex(LexType &curLex) {
- while (expPos < expStr.size() && expStr[expPos] == ' ')
- expPos++;
- if (expPos == expStr.size())
- curLex = END;
- else {
- char c = expStr[expPos];
- int pos = tSymbols.find(c);
- if (pos != -1) {
- curLex = (LexType)pos;
- expPos++;
- }
- else {
- // либо функция, либо число
- lexVal.clear();
- while (expPos < expStr.size() && !isSep(expStr[expPos]))
- lexVal += expStr[expPos++];
- if (isNum(lexVal))
- curLex = NUM;
- else if (isFunc(lexVal))
- curLex = FNC;
- else
- curLex = NAN;
- }
- }
- }
- bool calcExp(double &res);
- bool calcFunc(double &res) {
- // <Функция> = <ИмяФункции>(<Выражение>)
- string funcName = lexVal;
- nextLex(curLex);
- if (curLex != OPN)
- return false;
- nextLex(curLex);
- double arg =0.0;
- if (!calcExp(arg))
- return false;
- res = pfunc[FuncPos(funcName)](arg);
- return true;
- }
- bool calcMul(double &res) {
- // <Множитель> = +|- <ДробноеЧисло>|<Функция>|(<Выражение>)
- bool isNeg = false;
- if (curLex == PLS || curLex == MNS) {
- isNeg = curLex == MNS;
- nextLex(curLex);
- }
- switch(curLex) {
- case NUM:
- {
- res = toNum(lexVal);
- nextLex(curLex);
- break;
- }
- case FNC:
- {
- if (!calcFunc(res))
- return false;
- if (curLex != END)
- nextLex(curLex);
- break;
- }
- case OPN:
- {
- nextLex(curLex);
- if (!calcExp(res))
- return false;
- if (curLex != CLS)
- return false;
- nextLex(curLex);
- break;
- }
- default : return false;
- }
- res *= isNeg ? -1 : 1;
- return true;
- }
- bool calcTerm(double &res) {
- // <Слагаемое> = <Множитель>{*|/<Множитель>}
- if (!calcMul(res))
- return false;
- while (curLex == MUL || curLex == DIV) {
- LexType oper = curLex;
- double next = 0.0;
- nextLex(curLex);
- if (!calcMul(next))
- return false;
- switch(oper) {
- case MUL: res *= next; break;
- case DIV: res /= next; break; // DIV 0 запрещен по условию
- }
- }
- return true;
- }
- bool calcExp(double &res) {
- // <Выражение> = <Слагаемое>{+|-<Слагаемое>}
- if (!calcTerm(res))
- return false;
- while (curLex == PLS || curLex == MNS) {
- LexType oper = curLex;
- nextLex(curLex);
- double next = 0.0;
- if (!calcTerm(next))
- return false;
- switch(oper) {
- case PLS: res += next; break;
- case MNS: res -= next; break;
- }
- }
- return curLex == END || curLex == CLS;
- }
- void solve() {
- nextLex(curLex);
- double res = 0.0;
- if (calcExp(res))
- printf("%0.3f", res);
- else
- printf("Error");
- }
- int main() {
- freopen("input.txt","r",stdin);
- freopen("output.txt","w",stdout);
- input();
- solve();
- return 0;
- }
Editing is locked.