fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. #include <cmath>
  5. using namespace std;
  6.  
  7. //в этой функции рассмотрим все возможные операции, что могут встретиться в строке
  8. bool operation(char c){
  9. return c=='+' || c=='-' || c=='*' || c=='/' || c=='^';
  10. }
  11.  
  12. //данная функция будет возвращать приоритет поступившей операции
  13. int prioritet(char op){
  14. if(op<0) return 3;
  15. else{
  16. if(op == '+' || op == '-')return 1;
  17. else if(op == '*' || op == '/' )return 2;
  18. else if(op == '^')return 4;
  19. else return -1;
  20. }
  21. }
  22.  
  23. //следующая функция описывает принцип работы каждого оператора
  24. void action(vector<long> &value, char op){
  25. if(op<0){ //для унитарных операций
  26. long unitar=value.back();
  27. value.pop_back();
  28. if(-op=='-')value.push_back(-unitar);
  29. }
  30. else{ //для бинарных операций
  31. long right = value.back();
  32. value.pop_back();
  33. long left = value.back();
  34. value.pop_back();
  35. if(op=='+')value.push_back(left+right);
  36. else if(op=='-')value.push_back(left-right);
  37. else if(op=='*')value.push_back(left*right);
  38. else if(op=='/')value.push_back(left/right);
  39. else if(op=='^')value.push_back(pow(left,right));
  40. }
  41. }
  42.  
  43. long calculus(string &formula){
  44. bool unary=true; //создадим булевскую переменную, для распределения операторов на унарные и бинарные
  45. vector<long>value; //заведем массив для целых чисел
  46. vector<char>op; //и соответственно для самых операторов
  47. for(int i=0; i<formula.size(); i++){
  48. if(formula[i]=='('){ //если текущий элемент — открывающая скобка, то положим её в стек
  49. op.push_back('(');
  50. unary=true;
  51. }
  52. else if(formula[i]==')'){
  53. while(op.back()!='('){ //если закрывающая скобка - выполняем все операции, находящиеся внутри этой скобки
  54. action(value, op.back());
  55. op.pop_back();
  56. }
  57. op.pop_back();
  58. unary=false;
  59. }
  60. else if(operation(formula[i])){ //если данный элемент строки является одни из выше перечисленных операндов,то
  61. char zn=formula[i];
  62. if(unary==true)zn=-zn; //придает отрицательное значение, для распознавания функции унитарности оператора
  63. while(!op.empty() && prioritet(op.back())>=prioritet(zn)){
  64. action(value, op.back()); //выполняем сами алгебраические вычисления, где все уже операции упорядочены
  65. op.pop_back(); //в одном из стеков по строгому убыванию приоритета, если двигаться от вершины
  66. }
  67. op.push_back(zn);
  68. unary=true;
  69. }
  70. else{
  71. string number; //заведем строку для найденных числовых операндов
  72. while(i<formula.size() && isdigit(formula[i]))number+=formula[i++];//распознаем их с помощью библиотечной функции строк
  73. i--;
  74. value.push_back(atol(number.c_str()));//поместим в наш стек с числовыми выражениями
  75. unary=false;
  76. }
  77. }
  78. while(!op.empty()){ //выполним еще не использованные операции в стеке
  79. action(value, op.back());
  80. op.pop_back();
  81. }
  82. return value.back(); //получим на выходе значение выражения
  83. }
  84.  
  85. int main() {
  86. string formula,x; //введем две строки: сам многочлен/числовое выражение и по необходимости значение переменной
  87. cin>>formula>>x;
  88. if(x[0]=='-'){ //для слаженной работы унитарного минуса при отрицательном значении переменной, заключим его в скобки
  89. x.insert(x.begin(),'(');
  90. x.insert(x.end(),')');
  91. }
  92. int size=2*formula.size(); //зададим максимальный размер строки с учетом замены переменной
  93. for(int i=0; i<size; i++){
  94. if(formula[i]=='x'){
  95. formula.erase(i,1);
  96. formula.insert(i,x);//проведем замену
  97. }
  98. }
  99. cout<<calculus(formula); //выведем ответ
  100. return 0;
  101. }
Success #stdin #stdout 0s 15240KB
stdin
x^2-5*x+15-8*x^4
0
stdout
15