Como escrever uma calculadora de string com elegância (JAVA)

Calculadora de corda

Coordenadas 2020-4-24
passam-Huawei dois lados. O
entrevistador deu uma imagem dinâmica e me perguntou: você pode escrever uma calculadora de string simples em vinte minutos?
Pense um pouco: deve ficar tudo bem.
Então, na confusão de pensamentos, quero usar a recursão, mas também quero usar a pilha. Por fim, escrevi uma calculadora com incontáveis ​​anomalias de ponteiro nulo. Depois do fim, aprendi com ela e hoje ensino você a escrever uma calculadora de string.

Em primeiro lugar, devemos precisar de uma função para determinar se um caractere é um número,

 public static boolean isNum(char x){
    
    
        return x>=48 && x<=57;
    }//利用ascall码判断是否为数字

Com ele, passamos para a segunda etapa, projetando ideias de algoritmos.
Quanto à ideia de resolução de problemas da calculadora de string, só vi uma na Internet, que é usar a expressão polonesa do infixo para converter em um sufixo e calcular um por um. No processo de minha entrevista, minha primeira reação foi usar a recursão para reduzir todos os colchetes, e então calcular na ordem de multiplicação e divisão seguida de adição e subtração. Hoje vamos aprimorar as duas idéias.

Ideia 1: Expressão polonesa
Primeiro, examinamos a seguinte expressão 2 + 3 * (6-2). Essa expressão, que é a expressão que inserimos, é a expressão polonesa infixa. Nós a convertemos em uma expressão pós-fixada para obter Deve ser 2 3 6 2- * +
Qual regra você encontrou? Isso é colocar o operador após o número na ordem da operação. Quando calculamos, precisamos apenas de uma pilha para ajudar e podemos calcular o resultado em ordem. Acima.
Alguns amigos disseram, eu entendo a ideia, como escrever isso? Deixe-me falar devagar.

A primeira etapa, precisamos de algumas ferramentas auxiliares,
1. String

StringBuilder stringBuilder = new StringBuilder();

Use StringBuilder para armazenar a expressão de sufixo convertida.

2. Pilha

Stack<Character> stack = new Stack<>();

Usamos a pilha para auxiliar no armazenamento.

3. A forma do caractere da expressão original

char x[] = str.toCharArray();

Nós convertemos a string passada na função em uma matriz de caracteres, de modo que seja conveniente usar a função isNum para julgar

Então agora a função se parece com isto

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        retrun null;
        }

Em seguida, percorremos toda a matriz de caracteres

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<x.length;i++){
    
    

        }
        retrun null;
        }

Agora pense sobre isso, o que devemos fazer quando atravessamos o array?
Existem várias situações:
1. O caractere atual é um número
2. O caractere atual é um operador
3. O caractere atual é um colchete

No caso 1, precisamos apenas adicioná-lo ao resultado, porque em nossa expressão pós-fixada final, os números estão dispostos na ordem original.

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<x.length;i++){
    
    
            if (isNum(x[i])) {
    
     //该字符为数字,直接加入结果
                stringBuilder.append(x[i]);
                continue;
            }
        }
        retrun null;
        }

Alguns alunos disseram: E se houver vários dígitos? Fazemos algumas melhorias

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<x.length;i++){
    
    
            if (isNum(x[i])) {
    
     //该字符为数字,直接加入结果
                stringBuilder.append(x[i]);
                if ((i<x.length-1&&!isNum(x[i+1]))||i==x.length-1)){
    
    
                    stringBuilder.append(" ");
                }
                continue;
            }
        }
        retrun null;
        }

Nesta etapa, após adicionarmos o número ao resultado, fazemos um julgamento. Se o caractere atual já for o último caractere, adicionamos um espaço depois dele, ou, o próximo caractere do caractere atual não é um número, então também o adicionamos Adicione um espaço depois disso.

Nos casos 2 e 3
, a prioridade do símbolo / é maior que ± durante a operação , então processamos / primeiro , e quando encontramos * /, colocamos na pilha auxiliar

 if (x[i]=='*'||x[i]=='/'){
    
    
                stack.push(x[i]);
                continue;
            }

Parênteses têm maior prioridade do que multiplicação e divisão. O que devo fazer?
Pensando nas características da pilha, precisamos entrar na pilha quando encontrarmos o parêntese esquerdo, e por enquanto pensar que eles estão no mesmo nível da multiplicação e divisão, como segue

 if (x[i]=='*'||x[i]=='/'||x[i]=='('){
    
    
                stack.push(x[i]);
                continue;
            }

Depois de encontrar o parêntese esquerdo, ainda executamos as operações lógicas originais até encontrarmos um parêntese direito, que é a regra de correspondência entre parênteses.
Neste momento, precisamos operar na pilha e fazer um loop da pilha até encontrar o parêntese direito correspondente. Abrindo parênteses, concluímos uma conversão dentro do parêntese,

if (x[i]==')'){
    
    
                while (!stack.isEmpty()){
    
    
                    if (stack.peek()=='('){
    
    
                        stack.pop();
                        continue;
                    }
                    stringBuilder.append(stack.pop());
                }
                continue;
            }

Alguns alunos podem não achar que é muito vívido, vamos simular o conteúdo da pilha,
(3 + 4) antes do parêntese de fechamento,
o conteúdo da pilha é (+
e o conteúdo da string é 3 4
então, depois de estourarmos a pilha, o conteúdo da string O conteúdo torna-se 3 4 +
e não há nenhum operador entre colchetes na pilha.
Neste ponto, concluímos uma conversão de sufixo entre colchetes.

Neste momento, a barra está bem (riscada) - os alunos disseram novamente, que tal adição e subtração?
Ao encontrar adição e subtração, temos que considerar várias situações
1. A pilha atual está vazia e o símbolo é colocado diretamente na pilha
2. A pilha atual não está vazia e o elemento superior da pilha é (, indicando que ± é o operador entre colchetes, nós Também diretamente na pilha,
3. A pilha atual não está vazia, o elemento do topo da pilha não está (, indicando que ± pode estar entre parênteses, mas a ordem atual de operação ± deve ser organizada atrás do elemento do topo da pilha, depois de colocarmos a pilha, então ± colocar na pilha

if (x[i]=='+'||x[i]=='-'){
    
    
               while (!stack.isEmpty()&&stack.peek()!='('){
    
    
                   stringBuilder.append(stack.pop());
               }
               stack.push(x[i]);
               continue;
            }

Finalmente, adicionamos a instrução return para obter a expressão pós-fixada

return stringBuilder.toString();

A função completa é a seguinte

public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0;i<x.length;i++){
    
    
            if (isNum(x[i])) {
    
    
                stringBuilder.append(x[i]);
                if (((i<x.length-1&&!isNum(x[i+1]))||i==x.length-1)){
    
    
                    stringBuilder.append(" ");
                }
                continue;
            }
            if (x[i]=='*'||x[i]=='('||x[i]=='/'){
    
    
                stack.push(x[i]);
                continue;
            }
            if (x[i]==')'){
    
    
                while (!stack.isEmpty()){
    
    
                    if (stack.peek()=='('){
    
    
                        stack.pop();
                        continue;
                    }
                    stringBuilder.append(stack.pop());
                }
                continue;
            }
            if (x[i]=='+'||x[i]=='-'){
    
    
               while (!stack.isEmpty()&&stack.peek()!='('){
    
    
                   stringBuilder.append(stack.pop());
               }
               stack.push(x[i]);
               continue;
            }

        }
        return stringBuilder.toString();
    }

A próxima etapa é calcular o resultado da expressão de sufixo. Esta etapa é muito simples. Não vamos explicar isso. Precisamos apenas inserir o número na pilha, colocá-la na pilha ao encontrar o operador e empurrá-la novamente após obter o resultado do cálculo.
Nota / e - Você precisa inverter a ordem dos dois números retirados da pilha para calcular o resultado correto

public static Integer help(String str){
    
    
        Stack<Integer> num = new Stack<>();
        StringBuilder stringBuilder = new StringBuilder();
        char x[] = str.toCharArray();
        for (int i =0;i<x.length;i++){
    
    
            if (isNum(x[i])){
    
    
                stringBuilder.append(x[i]);
                if (i+1==x.length){
    
    
                    num.push(Integer.parseInt(stringBuilder.toString()));
                }
                if (x[i+1]==' '){
    
    
                    num.push(Integer.parseInt(stringBuilder.toString()));
                    stringBuilder.delete(0,stringBuilder.length());
                    continue;
                }
            }
            if (x[i]=='+'){
    
    
                num.push(num.pop()+num.pop());
            }
            if (x[i]=='-'){
    
    
                int a = num.pop();
                int b = num.pop();
                num.push(b-a);
            }
            if (x[i]=='*'){
    
    
                num.push(num.pop()*num.pop());
            }
            if (x[i]=='/'){
    
    
                int a = num.pop();
                int b = num.pop();
                num.push(b/a);
            }
        }
        return num.pop();
    }

Desta forma, chamamos duas funções na função principal para obter o resultado final do cálculo.

Veja o segundo artigo para recursão.

Acho que você gosta

Origin blog.csdn.net/qq_45789385/article/details/105733553
Recomendado
Clasificación