fork download
  1. #include <iostream>
  2. #include <string>
  3. #include <limits>
  4. #include <cctype>
  5. #include <stdexcept>
  6. #define err_msg(s) throw(std::domain_error(s))
  7.  
  8. //стек на базе динамического массива
  9. template<typename T>
  10. class mstack {
  11. private:
  12. T* arr;
  13. size_t cnt;
  14. size_t mem;
  15. public:
  16. mstack(void):arr(NULL),
  17. cnt(0),
  18. mem(8){}
  19. ~mstack(){
  20. this->clear();
  21. }
  22. mstack(const mstack&);
  23. mstack& operator = (const mstack&);
  24. public:
  25.  
  26. void push(const T& val){
  27. if(__alloc())
  28. arr[cnt++] = val;
  29. else
  30. err_msg("Ошибка при выделение памяти");
  31. }
  32.  
  33. void pop(void){
  34. if(cnt > 0)
  35. --cnt;
  36. else
  37. this->clear();
  38. }
  39.  
  40. void removeAt(size_t index){
  41. if(index < cnt){
  42. T* e = arr + (cnt - 1);
  43. for(T* p = arr + index; p < e; ++p)
  44. *p = *(p + 1);
  45. --cnt;
  46. }
  47. }
  48.  
  49. void clear(void){
  50. if(arr != NULL)
  51. delete[] arr;
  52. arr = NULL;
  53. cnt = 0;
  54. mem = 8;
  55. }
  56.  
  57. T& top(void) const { return arr[cnt - 1]; }
  58. T& top(void){ return arr[cnt - 1]; }
  59.  
  60. T& operator [] (int index) const {
  61. return arr[index];
  62. }
  63. T& operator [] (int index){
  64. return arr[index];
  65. }
  66.  
  67. size_t size(void) const {
  68. return cnt;
  69. }
  70.  
  71. bool empty(void) const {
  72. return (! cnt);
  73. }
  74. private:
  75.  
  76. bool __alloc(void) {
  77. if(arr == NULL){
  78. arr = new (std::nothrow) T[mem];
  79. if(arr == NULL)
  80. return false;
  81. } else if(cnt >= mem){
  82. size_t tmem = cnt + mem / 3;
  83. T* tmp = new (std::nothrow) T[tmem];
  84. if(tmp == NULL)
  85. return false;
  86.  
  87. T* e = arr + cnt;
  88. T* d = tmp;
  89. for(T* p = arr; p != e; ++p)
  90. *d++ = *p;
  91.  
  92. delete[] arr;
  93. arr = tmp;
  94. mem = tmem;
  95. }
  96. return true;
  97. }
  98. };
  99.  
  100.  
  101. //калькулятор только для целых чисел
  102. template<typename T>
  103. class expr {
  104. public:
  105.  
  106. static T calc(const char* s){
  107. const char* p = NULL;
  108. size_t cnt = 0;
  109. int scnt = 0;
  110. std::string sb;
  111.  
  112. for(p = s; *p; ++p){
  113. if(! isspace(*p))
  114. sb += *p;
  115.  
  116. if(*p == '(')
  117. ++scnt;
  118. else if(*p == ')')
  119. --scnt;
  120. }
  121.  
  122. if(scnt != 0)
  123. err_msg("Ошибка скобочных выражений");
  124. if(! sb.length())
  125. err_msg("Строка пуста");
  126.  
  127. p = NULL;
  128. return sub_calc(sb.c_str(), &p);
  129. }
  130.  
  131. private:
  132.  
  133. static T sub_calc(const char* s, const char** p){
  134. const char* t = s;
  135. T num, val;
  136. mstack<char> sops;
  137. mstack<T> sval;
  138. int neg = 0;
  139.  
  140. while(*s){
  141.  
  142. switch(*s){
  143. case '-':
  144. case '+':
  145. case '*':
  146. case '/':
  147. if((s == t) || ((s > t) && is_start(*(s - 1)))){
  148. neg = 1;
  149. ++s;
  150. break;
  151. }
  152. sops.push(*s++);
  153. break;
  154. case '(':
  155. val = sub_calc(s + 1, p);
  156. if(neg){
  157. val = 0 - val;
  158. neg = 0;
  159. }
  160. s = *p;
  161. sval.push(val);
  162. calc_muldiv(sval, sops);
  163. break;
  164. case ')':
  165. *p = s + 1;
  166. goto end;
  167. default:
  168.  
  169. if(! isdigit(*s))
  170. err_msg("Неизвестный символ");
  171.  
  172. s = to_number(s, val);
  173. if(neg){
  174. val = 0 - val;
  175. neg = 0;
  176. }
  177. sval.push(val);
  178. calc_muldiv(sval, sops);
  179. break;
  180. }
  181. }
  182. end:
  183. if(! sval.size())
  184. err_msg("Неожиданный конец");
  185.  
  186. num = sval[0];
  187. sval.removeAt(0);
  188. for(size_t i = 0; (i < sops.size()) && (i < sval.size()); ++i){
  189. switch(sops[i]){
  190. case '+':
  191. num += sval[i];
  192. break;
  193. case '-':
  194. num -= sval[i];
  195. break;
  196. }
  197. }
  198. sops.clear();
  199. sval.clear();
  200. return num;
  201. }
  202.  
  203. //приоритетные операции: умножение, деление
  204. static void calc_muldiv(mstack<T>& sval, mstack<char>& sops){
  205. T val;
  206. char ch;
  207.  
  208. while(! sops.empty()){
  209. ch = sops.top();
  210. if((ch == '+') || (ch == '-'))
  211. break;
  212.  
  213. val = sval.top();
  214. sval.pop();
  215. if(! sval.size())
  216. err_msg("Неожиданный конец");
  217.  
  218. if(ch == '*')
  219. sval.top() *= val;
  220. else if(ch == '/'){
  221. if(val == 0)
  222. err_msg("Деление на нуль!");
  223. sval.top() /= val;
  224. }
  225. sops.pop();
  226. }
  227. }
  228.  
  229. //конвертирование целых чисел из строки
  230. static const char* to_number(const char* s, T& n){
  231. static const T n_maxd = std::numeric_limits<T>::max() / 10;
  232. for(n = 0; *s && isdigit(*s); ++s){
  233. if(n >= n_maxd)
  234. err_msg("Переполнение числа!");
  235. n = n*10 + (T)(*s - '0');
  236. }
  237. return s;
  238. }
  239.  
  240. static bool is_start(char c){
  241. if(c == '+' || c == '-' || c == '*' || c == '/')
  242. err_msg("Лишний арифметический символ");
  243. return (c == '(');
  244. }
  245. };
  246.  
  247.  
  248. int main(void){
  249. try {
  250. short n = -(7)-4*10-(-(2*(((-(-(-(-(-8))/2))))+5*4))+5*2)+(-(20/10*20)/(-1*20-10/2*2+1)*1-2*3+4*5/6*7/1);
  251. char s[] = "-(7)-4*10-(-(2*(((-(-(-(-(-8))/2))))+5*4))+5*2)+(-(20/10*20)/(-1*20-10/2*2+1)*1-2*3+4*5/6*7/1)";
  252. short res = expr<short>::calc(s);
  253. std::cout << "my: " << res << std::endl;
  254. std::cout << "cpp: " << n << std::endl << std::endl;
  255. } catch(const std::domain_error& e){
  256. std::cout << e.what() << std::endl;
  257. }
  258.  
  259. //...
  260.  
  261. try {
  262. long n = -(10 + 20) / 4 + 201200 - 77 * 4*4/(-7) * (-(-7)-7) - 1 + 70 - 5*2/9 - (-1 + 2 * 6 - 1);
  263. char s[] = "-(10 + 20) / 4 + 201200 - 77 * 4*4/(-7) * (-(-7)-7) - 1 + 70 - 5*2/9 - (-1 + 2 * 6 - 1)";
  264. long res = expr<long>::calc(s);
  265. std::cout << "my: " << res << std::endl;
  266. std::cout << "cpp: " << n << std::endl << std::endl;
  267. } catch(const std::domain_error& e){
  268. std::cout << e.what() << std::endl;
  269. }
  270. return 0;
  271. }
Success #stdin #stdout 0s 3284KB
stdin
Standard input is empty
stdout
my:  -9
cpp: -9

my:  201251
cpp: 201251