Blog (9)
Komentarze (73)
Recenzje (0)
@pat.wasiewiczPiszemy trochę bardziej złożony kalkulator w C#.NET - #3 - Refactoring

Piszemy trochę bardziej złożony kalkulator w C#.NET - #3 - Refactoring

26.04.2013 00:40

Po batach o złych wcięciach (klik! ) poprawiam trochę kod: mam nadzieję, że jest trochę czytelniejszy.

Mógłbym podzelić go na mniejsze metody, ale myślę że w takiej formie sam algorytm (link w poprzednim poście) będzie trochę prostszy do wyczytania z kodu.

public static Expression FromInfix(string input)
{
    var output = new List<string>();
    var operators = new Stack<char>();

    // dzielimy ciągiem białych znaków
    var arguments = Regex.Split(input, @"\s+");

    foreach (var symbol in arguments)
    {
        // jeżeli dostaliśmy liczbę albo cokolwiek innego niż operator
        if (!Regex.IsMatch(symbol, @"^[\+|\*|/|(|)]$"))
        {
            output.Add(symbol);
            continue;
        }

        var exprOperator = Convert.ToChar(symbol);

        if (exprOperator.Equals('('))
        {
            operators.Push(exprOperator);
            continue;
        }

        if (exprOperator.Equals(')'))
        {
            var leftBracket = operators.Pop();
            while (!leftBracket.Equals('('))
            {
                output.Add(leftBracket.ToString());
                leftBracket = operators.Pop();
            }

            continue;
        }

        if (!exprOperator.Equals('*') && 
            !exprOperator.Equals('+') && 
            !exprOperator.Equals('/'))
        {
            continue;
        }

        // stos pusty albo operator na wierzchołku ma mniejszy priorytet
        if (operators.Count == 0 || 
            GetPriority(operators.Peek()) < GetPriority(exprOperator))
        {
            operators.Push(exprOperator);
            continue;
        }

        var top = operators.Peek();

        // zdejmij wszystkie operatory o wiekszym bądź równym priorytecie
        // i zapisz na wyjściu
        while (GetPriority(top) >= GetPriority(exprOperator) && 
                   operators.Count > 0)
        {
            output.Add(top.ToString());

            operators.Pop();
            top = operators.Peek();
        }

        // wrzuć na stos aktualny operator
        operators.Push(exprOperator);
    }

    // jeśli jakiś operator został na stosie, też go zapisz na wyjściu
    if (operators.Count == 1)
    {
        output.Add(operators.Peek().ToString());
    }

    // usuń pierwszą spację
    var expression = string.Join(" ", output.ToArray());
    return FromOnp(expression);
}
Wybrane dla Ciebie
Komentarze (5)