I am a student, and I am doing websites as freelancer. Lately I have started learning design patterns, refactoring, and test-driven development so that I can improve the maintainability, performance, and readability of my code.
I did some refactoring with method extracting in this case, but I got feedback that my code is trash.
Here is the main method. The whole Program
class is on GitHub.
/* main functionality
*
* parameter: expression - accepts string parameter and parses him, so it can calculate
*/
static double ParseCalculationString(string expression)
{
// currentNumberString will save current number
string currentNumberString = "";
// temporaryNumberString will be used for multiply/divide operations
string temporaryNumberString = "";
// we use this to access previous operator for calculating between numbers
char previousOperator = ' ';
// we use this for current operator that we get from from expression[i]
char currentOperator = ' ';
/* this is used for sum and subtract operations, we save operator and number here
so we can finish multiply and divide operations first, then we use number on hold
and operator on hold to add or deduct to total result. */
string numberOnHold = "";
char operatorOnHold = ' ';
/* total is used for saving total result, and currentNumberDouble for saving the number
* in the middle of multiply/divide operations */
double total = 0.0;
double currentNumberDouble = 0.0;
/* We use this two flags for marking the operation type, so we know what to calculate first */
bool flagMultiplyDivide = false;
bool flagSumSubtract = false;
int i;
for (i = 0; i < expression.Length; i++)
{
// checking if character is number, if yes we build number from the string until the character is symbol
if (char.IsNumber(expression[i]))
{
currentNumberString = currentNumberString + expression[i];
}
// I only wanted to limit to 4 symbols in this case, so I checked if current input character is * or / or - or +
else if (ValidateOperator(expression[i]))
{
currentOperator = expression[i];
// we jump into this condition if operator between two numbers is * or /
if (flagMultiplyDivide)
{
// if we multiply
if (previousOperator.Equals('*'))
{
currentNumberDouble = MultiplyNumbers(currentNumberString, temporaryNumberString);
}
// if we divide
else if (previousOperator.Equals('/'))
{
currentNumberDouble = DivideNumbers(temporaryNumberString, currentNumberString);
}
/* we have to use this condition if there is no more * or / operators after this number, therefore we can add our
multiply/divide result to total result*/
if (operatorOnHold.Equals('-') && (!currentOperator.Equals('*') && !currentOperator.Equals('/')))
{
total -= currentNumberDouble;
currentNumberDouble = 0.0;
}
else if (operatorOnHold.Equals('+') && (!currentOperator.Equals('*') && !currentOperator.Equals('/')))
{
total += currentNumberDouble;
currentNumberDouble = 0.0;
}
currentNumberString = "";
flagMultiplyDivide = false;
}
// we jump into this condition if operator between two numbers is + or -
else if (flagSumSubtract)
{
// if current operator is not * or / we can safely sum or subtract to total result(order of operations rule)
if (!currentOperator.Equals('*') && !currentOperator.Equals('/'))
{
if (operatorOnHold.Equals('+'))
{
total = ApplyNumberOnHold(total, numberOnHold, currentNumberString, true);
}
else if (operatorOnHold.Equals('-'))
{
total = ApplyNumberOnHold(total, numberOnHold, currentNumberString, false);
}
numberOnHold = "";
currentNumberString = "";
flagSumSubtract = false;
}
}
/* checking the current operators and setting the variables */
// multiply and divide operations
if (currentOperator.Equals('*') || currentOperator.Equals('/'))
{
// in case we have multiple consecutive multiply/divide operations 5*5*5*5
if (!currentNumberDouble.Equals(0.0))
{
currentNumberString = Convert.ToString(currentNumberDouble);
}
/* in case there is number and - or + after the number we can add it directly to total result
example for this: 5-5*5, which means that even if current operator is to multiply, we can safely
add or deduct our 5 to total result */
if (!numberOnHold.Equals(""))
{
total += Convert.ToDouble(numberOnHold);
numberOnHold = "";
}
temporaryNumberString = currentNumberString;
flagMultiplyDivide = true;
flagSumSubtract = false;
}
// sum and subtract operations
else if (currentOperator.Equals('+') || currentOperator.Equals('-'))
{
// used when checking, if previous operation was multiply/divide, so he can add result of that operation to total result
if (!currentNumberDouble.Equals(0.0))
{
if (operatorOnHold.Equals('-'))
total -= currentNumberDouble;
else
total += currentNumberDouble;
currentNumberDouble = 0.0;
}
// if we have consecutive add/subtract operations we directly add them to total result
if (!numberOnHold.Equals(""))
{
if (operatorOnHold.Equals('-'))
{
total -= Convert.ToDouble(numberOnHold);
}
else
{
total += Convert.ToDouble(numberOnHold);
}
}
numberOnHold = currentNumberString;
operatorOnHold = currentOperator;
flagSumSubtract = true;
flagMultiplyDivide = false;
}
currentNumberString = "";
previousOperator = currentOperator;
}
}
// if it is last character number, we have to check it after loop ends, because we can't loop no more
if (flagMultiplyDivide)
{
if (previousOperator.Equals('*'))
{
currentNumberDouble = MultiplyNumbers(currentNumberString, temporaryNumberString);
total = ApplyOperatorOnHold(operatorOnHold, total, currentNumberDouble);
}
else if (previousOperator.Equals('/'))
{
currentNumberDouble = DivideNumbers(temporaryNumberString, currentNumberString);
total = ApplyOperatorOnHold(operatorOnHold, total, currentNumberDouble);
}
}
else if (previousOperator.Equals('+'))
{
total = ApplyNumberOnHold(total, numberOnHold, currentNumberString, true);
}
else if (previousOperator.Equals('-'))
{
total = ApplyNumberOnHold(total, numberOnHold, currentNumberString, false);
}
return total;
}