Исходник транслятора математических выражений на C++


Добавил:DMT
Дата создания:25 апреля 2008, 16:57
Дата обновления:25 апреля 2008, 16:57
Просмотров:7119 последний позавчера, 16:44
Комментариев: 0
Исходник транслятора математических выражений на C++
Код на C++
  1. #include <conio.h>
  2. #include <iostream.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <ctype.h>
  6. #include <math.h>
  7. #include <stack.cpp>
  8.  
  9. void HelpFunc();
  10. void PutErrors(int NumErr,int Pos);
  11. int chifra(int num);
  12. int bukva(int num);
  13. int operand(int num);
  14. int prty(char x);
  15. long double fop(char op,long double a,long double b);
  16.  
  17.  
  18. enum { POW='^',MUL='*',DIV='/',PLUS='+',MINUS='-',NOT='!',AND='&',OR='|',
  19. LB='(',RB=')',POINT='.',
  20. //данные операторы заменяют функции син.кос.тан. и т.д.
  21. SIN='$',TG='`',COS='~',LOG=':',LN=';',EXP='@',FABS='#'};
  22.  
  23. char buffer[180], memory[180];
  24. int len,i=0,error=0,flagMin=0;//флаг отрицателной переменной
  25. long double value=0,a=0;
  26. TCStack st_op;//стек операторов
  27. TFStack st_num;//стек чисел
  28.  
  29. void main()
  30. {
  31. for(;;){
  32. clrscr();
  33. int skoba=0;
  34. error=0;
  35. while(st_op.nonEmpty())
  36. st_op.pop();
  37. while(st_num.nonEmpty())
  38. st_num.pop();
  39.  
  40. cout <<"exit - выход\n\t\t\t help-справка\n\n";
  41. cout << "Введите выражение: ";
  42. cin >> buffer;
  43. if(!strcmp(buffer,"exit")) exit(1);
  44. if(!strcmp(buffer,"help")) HelpFunc();
  45. len=strlen(buffer);
  46. for(i=0;i<len;i++)
  47. {
  48. //***** PROVERKA
  49. // на наличие скобок
  50. if(buffer[i]=='(') skoba++;
  51. if(buffer[i]==')') skoba--;
  52. if(skoba<0) {PutErrors(10,i);i=len-1;}//много )
  53. //***** END PROVERKA
  54. }
  55. i=0;
  56. if(skoba>0) PutErrors(9,skoba+2); //много (
  57. if(!error)
  58. do
  59. {
  60. int flag=0,flag1=0;
  61. flag=isdigit(buffer[i]);
  62. if(flag==0)
  63. {
  64. flag1=ispunct(buffer[i]);
  65. if(flag1==0) // может это пременная запрашиваем значение
  66. // и помещаем в глоб.переменную Value
  67. {
  68. int u=bukva(i);i=u-1;
  69. if(buffer[i+1]==NOT)
  70. PutErrors(2,i);
  71. if(flagMin==1) {value=-value;flagMin=0;}
  72. st_num.push (value);
  73. }
  74. else // усли это операнд или пунктуатор
  75. {
  76. int o=operand(i);i=o-1;
  77. switch(buffer[i])
  78. {
  79. case NOT:
  80. if(buffer[i+1]==AND || buffer[i+1]==OR ||
  81. buffer[i+1]==POW || buffer[i+1]==PLUS||buffer[i+1]==DIV||
  82. buffer[i+1]==MUL)
  83. PutErrors(2,i);
  84. else
  85. //после "!" идет ! ^ или число или "("
  86. st_op.push (buffer[i]); st_num.push(0);
  87. break;
  88.  
  89. case LB://после открыв.скб. идет & | ! / * + - (null)/(0)
  90. if(buffer[i+1]==AND || buffer[i+1]==OR ||
  91. buffer[i+1]==POW || buffer[i+1]==PLUS||buffer[i+1]==DIV||
  92. buffer[i+1]==MUL)
  93. PutErrors(1,i);
  94. if(buffer[i+1]==RB)
  95. PutErrors(5,i);
  96. else st_op.push (buffer[i]);
  97. break;
  98. case RB://после закр.скб. идет "(" или число
  99. if(buffer[i+1]==NOT||buffer[i+1]==LB||(isdigit(buffer[i+1]))) PutErrors(6,i);
  100. if(error==1)
  101. ;
  102. else { while (st_op.peek ()!=LB)
  103. st_num.push (fop (st_op.pop (), st_num.pop (), st_num.pop ()));
  104. st_op.pop (); }
  105. break;
  106. case AND: case OR: case POW:case MINUS:case PLUS:case MUL:
  107. case DIV:
  108. //после опрераторов идет ")" или число /!/&/|/^
  109. if(buffer[i+1]=='\0')
  110. PutErrors(1,i);
  111. if(buffer[i+1]==RB||((buffer[i]==POW||buffer[i]==AND||buffer[i]==OR||buffer[i]==PLUS)&&i==0)) PutErrors(1,i);
  112. if(buffer[i+1]==AND||buffer[i+1]==OR||buffer[i+1]==DIV||
  113. buffer[i+1]==POW||buffer[i+1]==MINUS||buffer[i+1]==PLUS||buffer[i+1]==MUL)
  114. PutErrors(4,i);
  115. if(MINUS&&isdigit(buffer[i+1])&&i!=0&&buffer[i-1]==LB)
  116. flagMin=1;
  117. else
  118. { while ((st_op.nonEmpty ())&&
  119. (prty (buffer[i])<=prty (st_op.peek ())))
  120. st_num.push (fop (st_op.pop (), st_num.pop (), st_num.pop ()));
  121. st_op.push (buffer[i]);
  122. }
  123. break;
  124. }
  125. }
  126. }
  127. else // если это цифра
  128. {
  129. int y=chifra(i);i=y-1;
  130. if(buffer[i+1]==NOT)
  131. PutErrors(2,i);
  132. if(flagMin==1) {a=-a;flagMin=0;}
  133. st_num.push (a);
  134. }
  135. i++;
  136. }while(i<len);
  137. if(error!=1)
  138. {while (st_op.nonEmpty ())
  139. st_num.push (fop (st_op.pop (), st_num.pop (), st_num.pop ()));
  140.  
  141. if(error==0)
  142. cout <<"\nРезультат: "<<st_num.pop ();
  143. }
  144. error=0;
  145. cout << "\nНажмите любую клавишу";
  146. getch();
  147. }
  148. }
  149. /********* Если это переменная? **********/
  150. int bukva(int num)
  151. {
  152. int flagb;
  153. char aa=buffer[num];
  154. strcpy(memory,&aa);
  155. //Если следующий символ-буква или цифра, но не опрератор, то
  156. //продолжаем перебор.
  157. do
  158. {
  159. num++;
  160. flagb=isalnum(buffer[num]);
  161. if(flagb!=0)
  162. {
  163. aa=buffer[num];
  164. strcat(memory,&aa);
  165. }
  166. }while(flagb!=0);
  167.  
  168. if(!strcmp(memory,"sin")&& buffer[num]==LB )
  169. st_op.push(SIN);
  170. else
  171. if(!strcmp(memory,"cos")&& buffer[num]==LB )
  172. st_op.push(COS);
  173. else
  174. if(!strcmp(memory,"tg")&& buffer[num]==LB )
  175. st_op.push(TG);
  176. else
  177. if(!strcmp(memory,"ln")&& buffer[num]==LB )
  178. st_op.push(LN);
  179. else
  180. if(!strcmp(memory,"log")&& buffer[num]==LB )
  181. st_op.push(LOG);
  182. else
  183. if(!strcmp(memory,"exp")&& buffer[num]==LB )
  184. st_op.push(EXP);
  185. else
  186. if(!strcmp(memory,"fabs")&& buffer[num]==LB )
  187. st_op.push(FABS);
  188. else
  189. if(buffer[num]==LB)
  190. PutErrors(3,num-1);
  191. else
  192. if(!error)
  193. {cout << "\nБыла введена переменная " << memory <<" Ведите значение ";
  194. cin >> value;
  195. }
  196.  
  197. return num;
  198. }
  199. //********** Если это число *********/
  200.  
  201. int chifra(int num)
  202. {
  203. a=0;
  204. int flagc=0;
  205. char aa=buffer[num];
  206. strcpy(memory,&aa);
  207. //если следующий символ-цифра, то продолжаем перебoр
  208. //если знак пунктуации или буква, то выходим.
  209. do{
  210. num++;
  211. flagc=isdigit(buffer[num]);
  212. if(flagc!=0)
  213. { aa=buffer[num]; strcat(memory,&aa); }
  214. }while(flagc!=0);
  215.  
  216. //Если пoсле цифры сразу идет буква, то это ошибка (выходим)
  217. if(isalpha(buffer[num]))
  218. PutErrors(6,num-1);
  219. if(ispunct(buffer[num])&&buffer[num]==POINT)
  220. {flagc=0;
  221. aa=buffer[num];
  222. strcat(memory,&aa);
  223. //если следующий символ-цифра, то продолжаем перeбoр
  224. //если знак пунктуации или буква, то выходим.
  225. do{
  226. num++;
  227. flagc=isdigit(buffer[num]);
  228. if(flagc!=0)
  229. { aa=buffer[num]; strcat(memory,&aa); }
  230. }while(flagc!=0);
  231. }
  232. if(ispunct(buffer[num])&&buffer[num]==POINT)
  233. PutErrors(12,num);
  234. //преобразуем строку цифр в число
  235. a=atof(memory);
  236. return num;
  237. }
  238. //******** Если это операнд или скобка
  239. int operand(int num)
  240. {
  241. char aa=buffer[num];
  242. switch(aa)
  243. {
  244. case AND:case OR:case LB:case RB: case NOT:case POW:
  245. case PLUS: case MINUS:case MUL:case DIV: case POINT:
  246. if((aa==POINT && num==0)||(aa==POINT && num!=0 && ispunct(buffer[num-1])))
  247. PutErrors(12,num-1);
  248. if(buffer[i]==NOT&&i==len-1)
  249. PutErrors(1,i);
  250. break;
  251. default:
  252. {PutErrors(7,num-1);}
  253. }
  254. strcpy(memory,&aa);
  255. return num+1;
  256. }
  257. //************* Приоритет операций ************
  258. int prty(char x)
  259. {
  260. switch(x)
  261. {
  262. case SIN:case COS:case TG:case LOG:case LN:case EXP:
  263. case FABS:
  264. return 6;
  265. case NOT:
  266. return 5;
  267. case POW:
  268. return 4;
  269. case MUL: case DIV:
  270. return 3;
  271. case AND:case OR:
  272. return 1;
  273. case PLUS:case MINUS:
  274. return 2;
  275. default:return 0;
  276. }
  277. }
  278. //**************** Выполнение действие
  279. long double fop(char op,long double a,long double b)
  280. {
  281. switch(op)
  282. {
  283. case NOT:
  284. {
  285. if(b>256&&b<0) PutErrors(13,i-1);
  286. else
  287. return (int)(255-b);}
  288. case POW: return (pow(a,b));
  289. case DIV: if(!b) PutErrors(11,i-2); else return (a/b);
  290. case MUL : return (a*b);
  291. case PLUS : return (a+b);
  292. case MINUS: return (a-b);
  293. case AND : return ((int)a&(int)b);
  294. case OR : return ((int)a|(int)b);
  295. case SIN : return sin(b);
  296. case COS : return cos(b);
  297. case TG : return tan(b);
  298. case LOG : return log10l(b);
  299. case LN : return logl(b);
  300. case EXP : return exp(b);
  301. case FABS : return fabs(b);
  302.  
  303. default: return 0;
  304. }
  305. }
  306. //BEGIN********* Функция вывода сообщений об ошибках *****************
  307. void PutErrors(int NumErr,int Pos)
  308. {
  309. error=1;
  310. cout <<"\n";
  311. for(int i=0;i<=Pos;i++)
  312. cout << buffer[i];
  313. switch(NumErr)
  314. {
  315. case 1:
  316. cout << "\nОШИБКА :\nПропущено число или переменная";
  317. break;
  318. case 2:
  319. cout << "\nОШИБКА :\nНе правильное использование оператора 'НЕ'!(число)";
  320. break;
  321. case 3:
  322. cout << "\nОШИБКА :\nМежду числом и левой скобкой отсутствует оператор";
  323. break;
  324. case 4:
  325. cout << "\nОШИБКА :\nДва оператора подряд";
  326. break;
  327. case 5:
  328. cout << "\nОШИБКА :\nВ скобках отсутствует выражение";
  329. break;
  330. case 6:
  331. cout << "\nОШИБКА :\nОтсутствует оператор";
  332. break;
  333. case 7:
  334. cout << "\nОШИБКА :\nНаберите help";
  335. break;
  336. case 8:
  337. cout << "\nОШИБКА :\nВ выражении присутствуют пробелы";
  338. break;
  339. case 9:
  340. cout << "\nОШИБКА :\nПропущена закрывающая скобка";
  341. break;
  342. case 10:
  343. cout << "\nОШИБКА :\nНет открывающей скобки";
  344. break;
  345. case 11:
  346. cout << "\nОШИБКА :\nДеление на ноль";
  347. break;
  348. case 12:
  349. cout << "\nОШИБКА :\nНе правильно введено число с плавающей точкой";
  350. break;
  351. case 13:
  352. cout << "\nОШИБКА :\nВведите число от 0 до 255";
  353. break;
  354.  
  355. }
  356. }
  357. //END************* Функция вывода сообщений об ошибках *********
  358. //**************** - help - *********
  359. void HelpFunc()
  360. {
  361. error=1;clrscr();
  362. cout <<"\n\t\t Транслятор алгебраических выражений"<<
  363. "\n\nВ данной программе используются следующие операторы и функции:"<<
  364. "\n\n sin(x)\n cos(x)\n tg(x)\n ln(x)\n log(x)\n fabs(x)"<<
  365. "\n !x\t\t\-'инвертирование'\n x&y\t\t-'И'\n x|y\t\t-'ИЛИ'\n x^y\t\t-'возведение в степень' "<<
  366. "\n x*y\t\t-'умножение'\n x/y\t\t-'деление'\n x+y\t\t-'сумма'\n x-y\t\t-'разность'";
  367. cout <<"\n\nПри использовании тригонометрических функций аргумент задается в радианах\n";
  368. }
При использовании обязательна ссылка на http://DMTSoft.ru
stack.cpp
Код на C++
  1.  
  2. class TFStack
  3. {
  4. private:
  5. long double num[1000];
  6. int inum;
  7.  
  8. public:
  9. TFStack () { inum=0; };
  10. ~TFStack () {};
  11. void push (long double &);
  12. long double pop ();
  13. long double peek ();
  14. int nonEmpty () { return inum; };
  15. };
  16.  
  17. void TFStack::push (long double &x)
  18. {
  19. num[inum++]=x;
  20. }
  21.  
  22. long double TFStack::pop ()
  23. {
  24. if (inum>0) return num[--inum]; else return 0;
  25. }
  26.  
  27. long double TFStack::peek ()
  28. {
  29. if (inum>0) return num[inum-1]; else return 0;
  30. }
  31.  
  32. // ‘⥪ бЁ¬ў®«м­ле §­ зҐ­Ё©
  33. class TCStack
  34. {
  35. private:
  36. int tok[1000], itok;
  37.  
  38. public:
  39. TCStack () { itok=0; };
  40. ~TCStack () {};
  41. void push (char &);
  42. char pop ();
  43. char peek ();
  44. int nonEmpty () { return itok; };
  45. };
  46.  
  47.  
  48. void TCStack::push (char &x)
  49. {
  50. tok[itok++]=x;
  51. }
  52.  
  53. char TCStack::pop ()
  54. {
  55. if (itok>0) return tok[--itok]; else return 0;
  56. }
  57.  
  58. char TCStack::peek ()
  59. {
  60. if (itok>0) return tok[itok-1]; else return 0;
  61. }
При использовании обязательна ссылка на http://DMTSoft.ru
up