Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

Высчитать значение выражения с приоритетами - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Двумерный массив через вектор http://www.cyberforum.ru/cpp-beginners/thread799073.html
Задача состоит в том, что надо создать массив строк через вектор, т.е. я хочу иметь возмость изменять как количество строк, так и их длину.
C++ Воспользовавшись указателями, поменяйте местами элементы массива с четными и нечетными индексами Решить задачи через Указатели... 3. Дан массив целых чисел. Воспользовавшись указателями, поменяйте местами элементы массива с четными и нечетными индексами (т.е. те элементы массива, которые... http://www.cyberforum.ru/cpp-beginners/thread799061.html
C++ Выбрать из строки все чётные цифры (нуль отнести к ним), если они есть в строке, и поместить их в первый динамический массив, и все нечётные цифры, ес
Решить задачи через Указатели... 2. .Пользователь вводит строку с клавиатуры (максимальная длина строки — 80 символов). Программа должна выбрать из строки все чётные цифры (нуль отнести к ним),...
Определить, является ли число a делителем числа b? C++
определить, является ли число a делителем числа b?
C++ Использование строк http://www.cyberforum.ru/cpp-beginners/thread799043.html
Помогите с алгоритмом программы: вводим текст происходит проверка на наличие цифр прописью, заменяет их и выводит исправленый текст...например ввод: "Вышли тридцать три богатыря.." вывод: "Вышли 33...
C++ нахождение целого числа по информации о его цифрах! в трехзначном числе зачеркнули его последнюю цифру когда в оставшимся двузначном числе переставили цифры а затем приписали к ним слева последнюю цифру числа x, то получилось число n. По заданному n... подробнее

Показать сообщение отдельно
TakeOver
41 / 31 / 1
Регистрация: 03.02.2013
Сообщений: 61
10.03.2013, 16:06
уу, совсем забыл, что обещал =(
на олимпиаду ездил, только приехал. вот исходник калькулятора нашел
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <iostream>
#include<vector>
#include<stdio.h>
#include <string>
#include<math.h>
#include<stack>
using namespace std;
#define MODIFER "%LG"
#define tod(x) strtod(x,NULL)
vector<string> args;//ОПН выражение для интерпритации
vector<string>stck;//временный стэк операторов
vector<string> inp;//вектор входных данных после препроцессоинга
inline int prior(const char c){
  switch(c){
    case '#': case '^':case '$'://#- корень, ^ -степень, $ - квадратный корень
      return 3;
    case '*': case '/':
      return 2;
    case '+': case '-':
      return 1;
  }
  return 0;
}
inline int sign(const long double a){
  return a>0?1:-1;
}
inline bool is_num(const char c){
  return ((c>='0'&&c<='9') || c=='.');//нет защиты от дурака, если больше 1 точки в числе.
}
inline bool is_oper(const char c){
  return prior(c);//логично, что если с - не оп-р то его приоритет =0
}
int main(){
  char c;
 
  //препроцессоинг входных данных
  while (scanf("%c",&c)!=EOF&& c!='='){
    if (c=='\n' || c==' ' || c=='\r' || c=='t')//для решения задачи это не нужно, но при дебагге пригодилось
      continue;
    //"извлекаем" числовые константы из данных
    if (is_num(c)){
      char t[1026];
      t[0]=c;
      long i=0;
      while (scanf("%c",&c)!=EOF && is_num(c)){//до тех пор пока в input'e есть цифры - читаем их
    t[++i]=c;
      }
      t[++i]='\0';//большн костылей больших и разных
      inp.push_back((const char *)t);
    }
    if (cin.eof() || c=='=')
      break;//больше костылей больших и разных
    if (c=='\n' || c==' ' || c=='\r' || c=='t')
      continue;
    //преобразуем квадратный корень
    if (c=='#' &&( inp.empty() || (!inp.empty() && (inp.back()[0]=='(' || prior(inp.back()[0])) ))){
//       inp.push_back("2");
//       inp.push_back("#");
    inp.push_back("$"); //пусть это будет знаком квадратного корня
    } else{
      //делаем вычетание из минуса, если дана отрицательная числовая константа
      if (c=='-' && (inp.empty() || inp.back()[0]=='(')){
    inp.push_back("0");
      }
      //заносим оператор.
      char t[2]; t[0]=c; t[1]='\0';
      inp.push_back((const char *)t);
    }
  }
#ifdef debug
  cout<<"infix notation after tokenizing:\n";
#endif
  //преобразование инфиксной записи в постфиксную ОПН через алгоритм Дейкстры
  for (auto &x:inp){
#ifdef debug
      cout<<x<<' ';
#endif
    if (is_num(x[0])){
      args.push_back(x);//тк нашел число, то помещаю его в конец выходного ОПН выражения
    } else if (x=="("){//помещение откр. скобки в стэк. потом уберется
      stck.push_back(x);
    } else if (x==")"){//нет защиты от дурака. если не будет найдена откр. скобка - значит в выражении ошибка
      while(stck.back()!="("){//перебрасываю все операторы из стэка в ОПН выражение, за искл. откр. скобки
    args.push_back(stck.back());
    stck.pop_back();
      }
      stck.pop_back();//скобка
    } else {//послий вариант - Х - оператор. пока приоритет оператора на вершине стэка выше Х - перебрасываю
//операторы из стэка в ОПН. заносу Х в стэк //в зависимости от ассоциативности. левая - меньше-равно, правая
//строго меньше
      while (!stck.empty() && is_oper(stck.back()[0]) && ((prior(stck.back()[0])>prior(x[0]) && x[0]=='$' )|| (prior(stck.back()[0])>=prior(x[0]) && x[0]!='$'))){//единственный право-ассоциативный оп-р - $.
    args.push_back(stck.back());
    stck.pop_back();
      }
      stck.push_back(x);
    }
  }//лексемы закончились. перебрасываю все ооператоры оставшиеся в стэка в ОПН
  while (!stck.empty()){
    args.push_back(stck.back());
    stck.pop_back();
  }
#ifdef debug
  cout<<"\nReverse Polish notation:\n";
  for(auto &x:args){
    cout<<x<<' ';
  }
  cout<<endl;
#endif
  //Интерпритация ОПН выражений, основанная на стэке.
stack<long double> top;//стэк чисел.
top.push(0);//на всякий случай занесу 0. хотя 99.997645677% что это лишнее
#define pop_to_reg(); \
a=top.top(); top.pop();\
b=top.top(); top.pop();
//tod - макрос strtod(x,NULL) преобразование в double
for(auto x=args.begin();x!=args.end();x++){
  if (is_num((*x)[0])){
    top.push(tod(x->c_str()));
  } else {
    register long double a,b; //полурегистры временных значений с вершин стэка.
    switch((*x)[0]){//взятие двух вернихних значений стэка - и помещение рез. операции на вершину стэка.
      case '+':
    pop_to_reg();
    top.push(a+b);
    break;
      case '-':
    pop_to_reg();
    top.push(b-a);
    break;
      case '*':
    pop_to_reg();
    top.push(a*b);
    break;
      case '/':
    pop_to_reg();
    top.push(b/a);
    break;
      case '$'://пришлось разделить корень по основанию и квадратный корень из-за левоассоциативности первого
    a=top.top(); top.pop();
    top.push(sqrt(a));
    break;
      case '#':
    pop_to_reg();
    //pow из math.h почему-то не берет нечетный корень из отриц. числа.
    //функция sign возвращает -1/1 в зависимости от знака числа. fabs - модуль числа.
    //корень = 1/(значение степени корня)
    //проверок за отриц. A и четное B не делается.
    top.push(sign(a)*pow(fabs(a),1.0/b));
    break;
      case '^':
    pop_to_reg();
    top.push(pow(b,a));
    break;
    }
  }
}
//ответ выражения лежит на вершине стэка.
#ifdef debug
  printf("Result=");
#endif
  printf(MODIFER,top.top());
  return 0;
}
правда, без переменных, если еще нужно, то могу скинуть полотно говнокода с переменными и с условиями и циклами(но не вложенными)
говнокод еще тот. писал тогда, когда только начал кресты изучать=)
проверок на ошибки - нет. можно добавить разве что проверку на скобки
1
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru