Вычитание калькулятора приводит к бесконечному циклу

Я работаю над калькулятором, который будет принимать данные от пользователя. Он должен решать такие выражения, как:

1+38*(!2)-5%37

Я работал над сложением и вычитанием, но столкнулся с проблемой.

У меня есть цикл, который ищет символы «+» или «-». Для «+» это работает, но для «-» всякий раз, когда я решаю выражение вроде

1-38

Это приводит меня к бесконечному циклу, так как результат этого выражения

-37

и цикл продолжает распознавать символ "-" как вычитание, но как минус 37.

Как решить эту проблему?

def symbols_exist(exp, symbols_list):
    """ Gets an expression string and a symbols list and returns true if any symbol
        exists in the expression, else returns false. """
    for s in symbols_list:
        if s in exp:
            return True
    return False

def BinaryOperation(exp, idx):
    """ Gets an expression and an index of an operator and returns a tuple with (first_value, operator, second_value). """
    first_value = 0
    second_value = 0

    #Get first value
    idx2 = idx -1
    while (idx2 > 0) and (exp[idx2] in string.digits):
        idx2 -=1

    first_value = exp[idx2:idx]

    #Get second value
    idx2 = idx +1
    while (idx2 < len(exp)) and (exp[idx2] in string.digits):
        idx2 += 1

    second_value = exp[idx+1:idx2]

    return (first_value, exp[idx], second_value)

def solve(exp):
    if not symbols_exist(exp, all_symbols):
        return exp

    idx = 0

    while idx < len(exp):
        if exp[idx] in string.digits:
            #Digit
            idx +=1
        elif exp[idx] in ("+", "-"):
            #Addition and Subtraction
            sub_exp = BinaryOperation(exp, idx)
            if sub_exp[1] == "+":
                value = int(sub_exp[0]) + int(sub_exp[2])
            else:
                value = int(sub_exp[0]) - int(sub_exp[2])

            value = str(value)

            exp = exp.replace(''.join(sub_exp), value)
            print exp

        return solve(exp)

person Lior    schedule 03.12.2012    source источник
comment
Вам нужно будет опубликовать часть своего кода, чтобы получить помощь здесь   -  person wim    schedule 03.12.2012
comment
Я не могу заставить вашу программу работать в любом случае, но не могли бы вы просто изменить symbols_exist так, чтобы она удаляла все начальные - перед поиском символа? (например, if exp[0] == '-': exp = exp[1:])   -  person Stuart    schedule 03.12.2012
comment
Это работает, но последняя строка (returnsolve(exp)) должна быть без отступа на 1 табуляцию.   -  person Stuart    schedule 04.12.2012


Ответы (1)


Возможное решение, объединяющее три функции в исходном примере. (EDIT: только что понял, что исходный ответ, который я опубликовал, можно немного упростить)

all_symbols = '+-'
def solve(expres):
    lhs, symbol, rhs = expres[0], None, ''
    for ch in expres[1:]:
        if symbol:
            rhs += ch
        elif ch in all_symbols:
            symbol = ch
        else:
            lhs += ch
    if symbol is '+':
        return int(lhs) + solve(rhs)
    if symbol is '-':
        return int(lhs) - solve(rhs)
    return int(expres)

print solve('1+5')

И еще один тип решения, который может быть полезен для рассмотрения

operations = [
    ('+', lambda a, b: a + b),
    ('-', lambda a, b: a - b)
    ]
def solve(exp):
    for symbol, operation in operations:
        p = exp.rfind(symbol)
        if p > 0:
            return operation(solve(exp[:p]), solve(exp[p + 1:]))
    return int(exp)
person Stuart    schedule 03.12.2012
comment
Я пытался сделать это с помощью рекурсии, поэтому я разработал разные функции. Что я пытаюсь сделать, так это решить самые сильные операторы в выражении, а затем снова вызвать Solve() с обновленным выражением, которое будет содержать решенные операторы (которые являются самыми сильными, например, мощность сильнее, чем умножение, а умножение сильнее, чем сложение или вычитание), - person Lior; 03.12.2012
comment
и рекурсия будет продолжать вызывать себя до тех пор, пока все выражение не станет числовым без каких-либо символов (поэтому базовое условие функцииsolve() проверяет, есть ли в выражении больше символов или нет). - person Lior; 03.12.2012
comment
Это предложение также использует рекурсию точно так, как вы описываете, и может быть адаптировано для решения самых сильных операторов в первую очередь. В любом случае, все, что вам нужно сделать, это игнорировать начальный '-' при проверке символов в выражении, что достигается с помощью if ch in all_symbols and n:, и посмотреть мой комментарий к вашему вопросу о том, как сделать то же самое в исходной программе. - person Stuart; 04.12.2012