Modificar peça de código para permitir que os flutuadores e os números negativos, bem como uma quantidade arbitrária de espaços entre os caracteres na cadeia introduzido

Eu sou ruim em python:

O seguinte trecho de código obtém uma string infix e irá convertê-lo para outfix e saída que nova expressão como uma string. No entanto ele não suporta números negativos ou carros alegóricos. O código a seguir permite apenas para valores de um dígito:

Tais como (0-9) nada como 10 ou 11. Caso contrário, ele lança um "erro fundamental" . Além disso, se eu adicionar um sinal negativo também lança um erro de chave.

class Stack:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[len(self.items)-1]

    def size(self):
        return len(self.items)

    def isNumber(self, txt):
        if not isinstance(txt,str) or len(txt.strip())==0:
            print("Argument error in isNumber")
            return False
        # YOUR CODE STARTS HERE
        try:
            float(txt)
            return True
        except ValueError:
            return False

#########################################################################################################

    def infixToPostfix(infixexpr):
        prec = {}
        prec["^"] = 4
        prec["*"] = 3
        prec["/"] = 3
        prec["+"] = 2
        prec["-"] = 2
        prec["("] = 1
        opStack = Stack()
        postfixList = []
        tokenList = infixexpr.split()

        for token in tokenList:
            if token in "0123456789":
                postfixList.append(token)
            elif token == '(':
                opStack.push(token)
            elif token == ')':
                topToken = opStack.pop()
                while topToken != '(':
                    postfixList.append(topToken)
                    topToken = opStack.pop()
            else:
                while (not opStack.isEmpty()) and \
                   (prec[opStack.peek()] >= prec[token]):
                      postfixList.append(opStack.pop())
                opStack.push(token)

        while not opStack.isEmpty():
            postfixList.append(opStack.pop())
        return " ".join(postfixList)

Então aqui está a minha correção para permitir que carros alegóricos, bem como:

Eu adicionei esta função:

def isNumber(x):
    try:
        float(x)
        return True
    except ValueError:
        return False

E mudou esta linha: if token in "0123456789":para isso:if Stack.isNumber(token):

E agora o código permite que carros alegóricos.


Então, qual é o outro problema? Bem, o outro problema é que meu código assume a seqüência de entrada vai ter exatamente um espaço entre cada um dos personagens, daí eu string.split () para colocar todos os personagens na lista. Exceto a seqüência de entrada pode ter uma quantidade arbitrária de espaços entre os caracteres, e se não há espaços, o meu código irá comparar algo como "((" a minha lista de caracteres e não encontrá-lo e lançar um erro Key . Então, já que Eu tenho que permitir que um número negativo (observado por um sinal de menos). Como posso modificar meu código para que ele não vai mais jogar a keyerrore me permite ter números negativos?


Quando eu fizer isso:

print(Stack.infixToPostfix("( ( 1 + 3 ) ) * 4 - ( 9.2 - 0 ) * ( 5 + 8 )"))

Meu código gera o seguinte: 1 3 + 4 * 9.2 0 - 5 8 + * -

Que funciona perfeitamente, no entanto se eu remover um espaço:

"(( 1 + 3 ) ) * 4 - ( 9.2 - 0 ) * ( 5 + 8 )"

Meu código não funciona mais. Erro Key '((' Eu sei porque ele lança este erro (explicação acima), mas eu não tenho certeza de como corrigi-lo.


Então TL pergunta final: DR

Como modificar meu código infixtopostfix para permitir uma quantidade arbitrária de espaços entre os caracteres e permitir números negativos?

Alex:

Primeiro crie uma função separada que irá produzir uma lista de tokens de sua corda. Um token é o número (sem sinal) ou um único caractere:

def tokenize(s):
    s = re.sub(r"\s+", "", s)
    result = []
    while (s):
        if s[0] in "0123456789":
            number = s[0]
            s = s[1:]
            while (s and s[0] in "0123456789."):
                number += s[0]
                s = s[1:]
            result.append(number)
            if s:
                result.append(s[0])
                s = s[1:]
        else:
            result.append(s[0])
            s = s[1:]
    return result

Em seguida, você precisa manter o controle das operações unárias mais e menos. Para fazer isso, apresentamos um especial 'neg' operação - quando você processar esta operação no postfix notação que você acabou de negar o valor no topo da pilha operando.

Você espera unárias mais e menos operações no início da string ou logo após a abertura '('. Depois de processar um número operando ou um fechamento ')' você redefinir o sinalizador unário para Falso, porque unário mais ou menos não pode aparecer em estas posições. Quando a bandeira unário é verdade que você deve manter rastreamento de entrada '+' e '-', utilize boolean flag 'neg' para ele. 'Neg' mudança de estado em cada '-'. Quando você finalmente encontrar um operando - verificar o estado de bandeira 'neg'. Se isso for verdade, então você precisa colocar a nossa operação especial 'neg' após o operando. Colocar uma operação 'neg' após o fechamento ')' é um pouco complicado e requer o uso de opStack.

def infixToPostfix(infixexpr):
        prec = {}
        prec["^"] = 3
        prec["*"] = 3
        prec["/"] = 3
        prec["+"] = 2
        prec["-"] = 2
        prec["("] = 1
        prec["neg"] = 1
        opStack = Stack()
        postfixList = []
        tokenList = tokenize(infixexpr)
        print(tokenList)

        unary = True
        neg = False

        for token in tokenList:
            if unary and token in "+-":
                if token == '-':
                     neg = not neg
            elif isNumber(token):
                postfixList.append(token)
                if neg:
                    postfixList.append("neg")
                    neg = False
                unary = False
            elif token == '(':
                if neg:
                    opStack.push("neg")
                    neg = False
                opStack.push(token)
                unary = True
            elif token == ')':
                topToken = opStack.pop()
                unary = False
                while topToken != '(':
                    postfixList.append(topToken)
                    topToken = opStack.pop()
                if not opStack.isEmpty() and opStack.peek() == "neg":
                    postfixList.append(opStack.pop())
            else:
                while (not opStack.isEmpty()) and \
                   (prec[opStack.peek()] >= prec[token]):
                      postfixList.append(opStack.pop())
                opStack.push(token)

        while not opStack.isEmpty():
            postfixList.append(opStack.pop())
        return " ".join(postfixList)

Entrada:

"-(( 1 + 3 ) ) * 4 - ( -9.2 - 0 ) * ( 5 + 8 ) - 4 * (-2)"

Resultado:

1 3 + neg 4 * 9.2 neg 0 - 5 8 + * - 4 2 neg * -

ATUALIZAR

Se você quiser números processo negativas como um único negativa operando e não como um operando positivo seguido por uma operação de 'neg', então você só precisa de uma pequena modificação do método infixToPostfix. Você só precisa modificar o elif isNumber(token)ramo. Vou colocá-lo embora aqui completa:

def infixToPostfix(infixexpr):
        prec = {}
        prec["^"] = 3
        prec["*"] = 3
        prec["/"] = 3
        prec["+"] = 2
        prec["-"] = 2
        prec["("] = 1
        prec["neg"] = 1
        opStack = Stack()
        postfixList = []
        tokenList = tokenize(infixexpr)

        unary = True
        neg = False

        for token in tokenList:
            if unary and token in "+-":
                if token == '-':
                     neg = not neg
            elif isNumber(token):
                if neg:
                    postfixList.append("-" + token)
                else:
                    postfixList.append(token)
                neg = False
                unary = False
            elif token == '(':
                if neg:
                    opStack.push("neg")
                    neg = False
                opStack.push(token)
                unary = True
            elif token == ')':
                topToken = opStack.pop()
                unary = False
                while topToken != '(':
                    postfixList.append(topToken)
                    topToken = opStack.pop()
                if not opStack.isEmpty() and opStack.peek() == "neg":
                    postfixList.append(opStack.pop())
            else:
                while (not opStack.isEmpty()) and \
                   (prec[opStack.peek()] >= prec[token]):
                      postfixList.append(opStack.pop())
                opStack.push(token)

        while not opStack.isEmpty():
            postfixList.append(opStack.pop())
        return " ".join(postfixList)

Agora, a saída é

1 3 + neg 4 * -9.2 0 - 5 8 + * - 4 -2 * -

Acho que você gosta

Origin http://43.154.161.224:23101/article/api/json?id=278071&siteId=1
Recomendado
Clasificación