Транслятор математических выражений на Си


Добавил:DMT
Дата создания:1 мая 2008, 17:57
Дата обновления:1 мая 2008, 18:01
Просмотров:8039 последний позавчера, 1:24
Комментариев: 0
Транслятор математических выражений на Си
Текст программы
Код на C++
  1. #include <iostream.h>
  2. #include <stdio.h>
  3. #include <conio.h>
  4. #include <ctype.h>
  5. #include <math.h>
  6. #include "stack.cpp"
  7.  
  8. class TFStack
  9. {
  10. private:
  11. long double num[1000];
  12. int inum;
  13.  
  14. public:
  15. TFStack () { inum=0; };
  16. ~TFStack () {};
  17. void push (long double &);
  18. long double pop ();
  19. long double peek ();
  20. int nonEmpty () { return inum; };
  21. };
  22.  
  23. void TFStack::push (long double &x)
  24. {
  25. num[inum++]=x;
  26. }
  27.  
  28. long double TFStack::pop ()
  29. {
  30. if (inum>0) return num[--inum]; else return 0;
  31. }
  32.  
  33. long double TFStack::peek ()
  34. {
  35. if (inum>0) return num[inum-1]; else return 0;
  36. }
  37.  
  38. class TCStack
  39. {
  40. private:
  41. int tok[1000], itok;
  42.  
  43. public:
  44. TCStack () { itok=0; };
  45. ~TCStack () {};
  46. void push (char &);
  47. char pop ();
  48. char peek ();
  49. int nonEmpty () { return itok; };
  50. };
  51.  
  52.  
  53. void TCStack::push (char &x)
  54. {
  55. tok[itok++]=x;
  56. }
  57.  
  58. char TCStack::pop ()
  59. {
  60. if (itok>0) return tok[--itok]; else return 0;
  61. }
  62.  
  63. char TCStack::peek ()
  64. {
  65. if (itok>0) return tok[itok-1]; else return 0;
  66. }
  67.  
  68.  
  69. enum token_val {
  70. NUMBER,
  71. ADD='+', SUB='-', MUL='*', DIV='/', EXP='^',
  72. BIG='>', SML='<', EQU='=', MOD='%', AND='&',
  73. OR ='|', FAC='!', LBR='(', RBR=')', END='~'
  74. };
  75.  
  76. token_val cur_tok;
  77.  
  78. enum { false, true };
  79.  
  80. int flDigit, flOp, flAlpha, flLB, flRB, flUSub;
  81.  
  82.  
  83. // Синтаксический разбор выражения
  84.  
  85. int Err (int num, int pos)
  86. { char *e;
  87.  
  88. for (int i=0; i<pos; *(e+i++)=' '); *(e+pos)='\0';
  89. cout << e << " ^ - ";
  90. switch (num)
  91. {
  92. case 1: cout << "Пропущена операция, либо ошибочная переменная!\n";
  93. break;
  94. case 2: cout << "Пропущена операция!\n";
  95. break;
  96. case 3: cout << "Пропущена переменная / число!\n";
  97. break;
  98. case 4: cout << "Отсутствует выражение!\n";
  99. break;
  100. case 5: cout << "Неверная лексема!\n";
  101. break;
  102. case 6: cout << "Пропущена парная закрывающая скобка!\n";
  103. break;
  104. case 7: cout << "Лишняя закрывающая скобка!\n";
  105. break;
  106. case 8: cout << "Пропущена операция, либо лишняя закрывающая скобка!\n";
  107. break;
  108. };
  109. return 1;
  110. }
  111.  
  112. void SetFlags (char ch)
  113. {
  114. switch (ch)
  115. {
  116. case LBR:
  117. flDigit=true; flOp=false; flAlpha=true;
  118. flLB =true; flRB=false; flUSub =true; break;
  119. case RBR:
  120. flDigit=false; flOp=true; flAlpha=false;
  121. flLB =false; flRB=true; flUSub =false; break;
  122. case '0': case '1':case '2':case '3': case '4':
  123. case '5': case '6':case '7':case '8': case '9':
  124. flDigit=true; flOp=true; flAlpha=false;
  125. flLB =false; flRB=true; flUSub =false; break;
  126. case EXP: case MUL: case DIV: case ADD: case SUB:
  127. case BIG: case SML: case EQU: case MOD: case AND:
  128. case OR :
  129. flDigit=true; flOp=false; flAlpha=true;
  130. flLB =true; flRB=false; flUSub =false; break;
  131. case FAC:
  132. flDigit=false; flOp=true; flAlpha=false;
  133. flLB =false; flRB=true; flUSub =false; break;
  134. default:
  135. if (isalpha (ch))
  136. {
  137. flDigit=true; flOp=true; flAlpha=true;
  138. flLB =false; flRB=true; flUSub =false;
  139. };
  140. }
  141. }
  142.  
  143. int DetectSintax (char *Str)
  144. { char ch, pch;
  145. int CB=0;
  146.  
  147. flDigit=true; flOp=false; flAlpha=true;
  148. flLB =true; flRB=false; flUSub =true;
  149. for (int i=0; (ch=*(Str+i))!='\0'; i++)
  150. {
  151. switch (ch)
  152. {
  153. case '0': case '1':case '2':case '3': case '4':
  154. case '5': case '6':case '7':case '8': case '9': case '.':
  155. if (flDigit) SetFlags (ch); else { Err (2, i); return 0; }
  156. break;
  157. case EXP: case MUL: case DIV: case ADD: case SUB:
  158. case BIG: case SML: case EQU: case MOD: case AND:
  159. case OR : case FAC:
  160. if (flUSub) SetFlags (ch);
  161. else if (flOp) SetFlags (ch);
  162. else { Err (3, i); return 0; };
  163. break;
  164. case LBR:
  165. if (flLB) { SetFlags (ch); CB++; }
  166. else if (isdigit (pch)||isalpha (pch)) { Err (2, i); return 0; }
  167. else { Err (8, i); return 0; }
  168. break;
  169. case RBR:
  170. if (flRB) { SetFlags (ch); CB--; }
  171. else if (pch==LBR) { Err (4, i); return 0; }
  172. else if (pch==EXP||pch==MUL||pch==DIV||pch==ADD||pch==SUB||
  173. pch==BIG||pch==SML||pch==EQU||pch==MOD||pch==AND||
  174. pch==OR||pch==FAC) { Err (3, i); return 0; }
  175. break;
  176. default:
  177. if (isalpha (ch))
  178. {
  179. if (flAlpha) SetFlags (ch);
  180. else if (isdigit (pch)) { Err (1, i); return 0; }
  181. else if (pch==RBR) { Err (2, i); return 0; }
  182. }
  183. else { Err (5, i); return 0; }
  184. } pch=ch;
  185. };
  186. if (((ch=*(Str+i-1))!=RBR)&&(!isalpha (ch))&&
  187. (!isdigit (ch))&&(ch!=FAC)) { Err (3, i); return 0; }
  188. else if (ch==FAC&&i==1) { Err (3, 0); return 0; }
  189. else if (CB>0) { Err (6, i); return 0; }
  190. else if (CB<0) { Err (7, i-1); return 0; }
  191. return 1;
  192. }
  193.  
  194.  
  195. // Непосредственно вычисление выражения
  196.  
  197. token_val get_token (double *arg, FILE *f)
  198. { char ch, *var;
  199.  
  200. do
  201. if (((ch=fgetc (f))==EOF)||(ch=='\n')||(ch==0)) return END;
  202. while ((ch!='\n') && (isspace (ch)));
  203.  
  204. switch (ch)
  205. {
  206. case EXP: case MUL: case DIV: case ADD: case SUB:
  207. case BIG: case SML: case EQU: case MOD: case AND:
  208. case OR : case FAC: case LBR: case RBR:
  209. return cur_tok=(token_val) ch;
  210. case '0': case '1': case '2': case '3': case '4':
  211. case '5': case '6': case '7': case '8': case '9':
  212. ungetc (ch, f); *arg=0;
  213. fscanf (f,"%lf", arg);
  214. return cur_tok=NUMBER;
  215. default:
  216. int i=0;
  217. *(var+i++)=ch;
  218. while (isalpha (ch=fgetc (f))||isdigit (ch)) *(var+i++)=ch;
  219. *(var+i)='\0'; ungetc (ch, f);
  220. cout << var << "="; cin >> *arg;
  221. return cur_tok=NUMBER;
  222. };
  223. }
  224.  
  225. long double fop (char op, double a, double b)
  226. {
  227. switch (op)
  228. {
  229. case EXP: return pow (a, b);
  230. case MUL: return a*b;
  231. case DIV: if (b!=0) return a/b; else return 0;
  232. case ADD: return a+b;
  233. case SUB: return a-b;
  234. case BIG: return a>b;
  235. case SML: return a<b;
  236. case EQU: return a==b;
  237. case MOD: return (int)a%(int)b;
  238. case AND: return (int)a&(int)b;
  239. case OR : return (int)a|(int)b;
  240. case FAC: long double f=1;
  241. for (int i=1; i<=(int)a; f*=i++);
  242. return f;
  243. default : return 0;
  244. }
  245. }
  246.  
  247. int prty (token_val t)
  248. {
  249. switch (t)
  250. {
  251. case FAC: return 4;
  252. case EXP: return 3;
  253. case MUL: case DIV: return 2;
  254. case ADD: case SUB: case BIG: case SML:
  255. case EQU: case MOD: case AND: case OR: return 1;
  256. default: return 0;
  257. }
  258. }
  259.  
  260. long double Exec ()
  261. { TCStack st_op;
  262. TFStack st_num;
  263. token_val t;
  264. double x;
  265.  
  266. while ((t=get_token (&x, f))!=END)
  267. {
  268. switch (t)
  269. {
  270. case NUMBER:
  271. st_num.push (x); break;
  272. case LBR:
  273. st_op.push (t); break;
  274. case RBR:
  275. while (st_op.peek ()!=LBR)
  276. st_num.push (fop (st_op.pop (), st_num.pop (), st_num.pop ()));
  277. st_op.pop (); break;
  278. case MUL: case DIV: case ADD: case SUB:
  279. case EXP: case BIG: case SML: case EQU:
  280. case MOD: case AND:case OR:
  281. while ((st_op.nonEmpty ())&&
  282. (prty (t)<=prty ((token_val) st_op.peek ())))
  283. st_num.push (fop (st_op.pop (), st_num.pop (), st_num.pop ()));
  284. st_op.push (t); break;
  285. case FAC:
  286. st_num.push (fop (t, st_num.pop (), 0));
  287. break;
  288. }
  289. }
  290.  
  291. while (st_op.nonEmpty ())
  292. st_num.push (fop (st_op.pop (), st_num.pop (), st_num.pop ()));
  293. return st_num.pop ();
  294. }
  295.  
  296. void main ()
  297. { char str[100]="\x0";
  298.  
  299. clrscr ();
  300. do
  301. {
  302. cout << ">> "; cin >> str;
  303. if (str[0]=='q') break;
  304. if (str[0]=='c') clrscr ();
  305. else
  306. {
  307. if (DetectSintax (str)) cout << Exec () << "\n";
  308. };
  309. }
  310. while (1);
  311. }
При использовании обязательна ссылка на http://DMTSoft.ru
up