Guest User

Untitled

a guest
Jul 19th, 2018
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.95 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3.  
  4. using Value = System.Double; // double is now Value, since all values here are double
  5. using POperand = SharedPtr<Operand>; // POperator is a new datatype declaration, it specifies a Pointer Operand
  6.  
  7. class Operand{
  8. public virtual Value Apply(Value vX);
  9. };
  10.  
  11. class BinaryOperator: Operand{
  12. private POperand m_poFirst;
  13. private POperand m_poSecond;
  14.  
  15. public BinaryOperator(POperand poFirst, POperand poSecond)
  16. {
  17. this.m_poFirst = poFirst;
  18. this.m_poSecond = poSecond;
  19. }
  20.  
  21. public POperand GetFirst()
  22. {
  23. return m_poFirst;
  24. }
  25.  
  26. public POperand GetSecond()
  27. {
  28. return m_poSecond;
  29. }
  30. };
  31.  
  32. class Constant: Operand{ // Constant class is meant to handle numerical or Constant expressions
  33. public Constant(Value vValue){
  34. this.m_vValue = vValue; // Initalise member m_vValue
  35. }
  36. public virtual Value Apply(Value vX){
  37. return m_vValue; // If a value is passed to Apply, it is overridden with m_vValue numerical constant
  38. }
  39.  
  40. private Value m_vValue;
  41. };
  42.  
  43. class Variable: Operand{ // To handle variables like x,y
  44. public Variable(){}
  45.  
  46. virtual Value Apply(Value vX){
  47. return vX; // This is where we replace varibles with a numerical value
  48. }
  49. };
  50.  
  51. // Start operator classes
  52.  
  53. class Add: BinaryOperator
  54. {
  55. public Add(POperand poFirst, POperand poSecond):BinaryOperator(poFirst, poSecond)
  56. {}
  57.  
  58. public virtual Value Apply(Value vX){
  59. return GetFirst()->Apply(vX) + GetSecond()->Apply(vX); // Application of values should be to operands
  60. }
  61. };
  62.  
  63. class Subtract: BinaryOperator{
  64. public Subtract(POperand poFirst, POperand poSecond){
  65. BinaryOperator(poFirst, poSecond);
  66. }
  67. virtual Value Apply(Value vX){
  68. return GetFirst()->Apply(vX) - GetSecond()->Apply(vX);
  69. }
  70. };
  71.  
  72. class Multiply: BinaryOperator{
  73. public Multiply(POperand poFirst, POperand poSecond){
  74. return BinaryOperator(poFirst, poSecond);
  75. }
  76.  
  77. public virtual Value Apply(Value vX){
  78. return GetFirst()->Apply(vX) * GetSecond()->Apply(vX);
  79. }
  80. };
  81.  
  82. class Divide: BinaryOperator{
  83. public Divide(POperand poFirst, POperand poSecond){
  84. return BinaryOperator(poFirst, poSecond)
  85. }
  86. public virtual Value Apply(Value vX){
  87. return GetFirst()->Apply(vX) / GetSecond()->Apply(vX);
  88. }
  89. };
  90.  
  91. class Exponentiate: BinaryOperator{
  92. public Exponentiate(POperand poFirst, POperand poSecond)
  93. {
  94. return BinaryOperator(poFirst, poSecond)
  95. }
  96.  
  97. virtual Value Apply(Value vX){
  98. return pow(GetFirst()->Apply(vX), GetSecond()->Apply(vX));
  99. }
  100. };
  101.  
  102. // End operator classes
  103.  
  104. public interface IopFunction(POperand poFirst, POperand poSecond);
  105.  
  106. POperand Create(POperand poFirst, char cOperator, POperand poSecond){ // Factory function
  107. if(cOperator=='+') IopFunction = Add(poFirst, poSecond);
  108. else if(cOperator=='-') IopFunction = Subtract(poFirst, poSecond);
  109. else if(cOperator=='*') IopFunction = Multiply(poFirst, poSecond);
  110. else if(cOperator=='/') IopFunction = Divide(poFirst, poSecond);
  111. else if(cOperator=='^') IopFunction = Exponentiate(poFirst, poSecond);
  112. }
  113.  
  114. Value ReadValue(const char* sData, int& nPos){ // Read a Value from sData, starting at nPos; purpose is to return vValue
  115. int nEnd = nPos + 1; // Stop reading at nPos+1
  116.  
  117. while(1){ // Purpose of the loop is to extract one number sans decimals from sData
  118. char cCh = sData[nEnd];
  119. if(!(cCh == '.' || (cCh >= '0' && cCh <= '9')) || cCh == 0) break;
  120. nEnd++;
  121. }
  122.  
  123. std::string sNumber(sData + nPos, nEnd - nPos); // string sNumber now created the number as a char string
  124. Value vValue;
  125. std::istringstream(sNumber) >> vValue; // Transfer cahr string to Value alias double, variable vValue
  126. nPos = nEnd; // I've read until nEnd and extracted vValue for you
  127.  
  128. return vValue;
  129. }
  130.  
  131. POperand ReadBinary(const char* sData, int& nPos); // Prototype, required for ReadUnary
  132.  
  133. POperand ReadUnary(const char* sData, int& nPos){ // nPos belongs to main()
  134. int cCh = sData[nPos];
  135.  
  136. if(cCh == '('){
  137. nPos++;
  138. POperand poOperator = ReadBinary(sData, nPos); // Call ReadBinary, which in turn calls us back
  139. nPos++;
  140. return poOperator;
  141. }
  142. else if(cCh == '-' || cCh == '.' || (cCh >= '0' && cCh <= '9')){ // Literal
  143. return POperand(new Constant(ReadValue(sData, nPos))); // Constant and Variables are like objects
  144. }
  145. else if(cCh == 'x'){
  146. nPos++;
  147. return POperand(new Variable());
  148. }
  149. else{
  150. // Bad! Stop parsing here
  151. exit(0); // Not for production use!
  152. }
  153. }
  154.  
  155. /*
  156. 1 Read the first element (unary expression)
  157. 2 Read the next element (operator)
  158.  
  159.  
  160. 3.0 If the operator is *, read the next operand (unary expression)
  161. 3.1 Create a unary expression with (first unary expression)(operator)(second unary expression)
  162. 3.2 Set that expression to (first unary expression) and goto 2
  163.  
  164.  
  165. 3'.0 If the operator is +, read an operand (unary expression)
  166. 3'.1 Read an operator
  167.  
  168.  
  169. 3'.1.1.0 If the operator is *
  170. 3'.1.1.1 Put back the second unary expression
  171. 3'.1.1.2 Call ReadBinary, (recursive), which returns the new (second unary expression)
  172. 3'.1.1.3 Goto 3'.1.1'
  173.  
  174. 3'.1.1'.0 If the operator is +
  175. 3'.1.1'.1 Create a unary expression with (first unary expression)(operator)(second unary expression)
  176. */
  177.  
  178. inline int Level(const int &cOperator){
  179. if(cOperator == '+' || cOperator == '-')return 1;
  180. else if(cOperator == '*' || cOperator =='/')return 2;
  181. else if(cOperator == '^')return 3;
  182. }
  183.  
  184. POperand ReadBinary(const char* sData, int& nPos){ // nPos belongs to main()
  185. POperand poFirst = ReadUnary(sData, nPos); // Do not confuse with the m_ counterparts
  186. POperand poSecond;
  187.  
  188. while(nPos < strlen(sData)){
  189. int cFirstOperator = sData[nPos]; // cFirstOperator expects an operator
  190. nPos++;
  191. int nOldPos = nPos; // We might have to fall back on the old value
  192. poSecond = ReadUnary(sData, nPos);
  193.  
  194. int cSecondOperator = sData[nPos];
  195. if(Level(cFirstOperator) < Level(cSecondOperator)){
  196. nPos = nOldPos; // Put back poSecond
  197. poSecond = ReadBinary(sData, nPos); // Recursion
  198. }
  199. poFirst = Create(poFirst, cFirstOperator, poSecond);
  200. continue;
  201. }
  202. return poFirst;
  203. }
  204.  
  205. public int main(string[] args){
  206. System.Console.WriteLine("Enter expression to evaluate: ");
  207. string sValue;
  208. std::getline(std::cin, sValue); // The reading from stdin is done here
  209.  
  210. int nPos = 0; //nPos belongs to main(), always passed by reference
  211. Value vApplyValue;
  212. std::cout << "Enter value to replace x with (if applicable): ";
  213. std::cin >> vApplyValue;
  214. std::cout << (ReadBinary(sValue.c_str(), nPos)->Apply(vApplyValue)) << std::endl;
  215.  
  216. return 0;
  217. }
Add Comment
Please, Sign In to add comment