首页 > Java > java教程 > 正文

练习 - 使用终端模拟银行账户

PHPz
发布: 2024-08-12 22:43:49
原创
345 人浏览过

稍微脱离理论,训练营的下一步是练习(他们称之为项目挑战)。我认为包含一个实用部分来巩固到目前为止所涵盖的内容会很有趣。

要求创建一个模拟银行单个账户的项目,包含分行号码账号客户姓名平衡。该数据必须来自终端,最后必须显示一条消息,说明帐户已成功创建并显示输入的数据。原始描述可以在这里查看。

嗯,看起来很简单。但在我收到的任何任务中,我真正喜欢做的一件事是将其分解为非常短的步骤,以便我有一个清晰的路径可以遵循。我这样做也是因为当我在脑海中绘制流程时,我可以理解它是否符合所要求的内容,并且如果我认为它不起作用,我可以快速改变行动方针。

Exercício - Simulando Uma Conta Bancária Através Do Terminal

因此,要遵循的步骤如下:

  1. 创建一个类来“容纳”终端中接收的数据和帐户创建方法;
  2. 向用户询问数据,读取终端输入的信息并将其存储在变量中;
  3. 向用户显示确认消息,将变量组织成可读的字符串。

看起来并不复杂。从第 1 步开始,我们有以下内容:

TerminalAccount.java

public class TerminalAccount { // eu sei, sou muito criativo
    private int branch;
    private String account;
    private String clientName;
    private double balance;

    public void createAccount(){
        // aqui a mágica acontece
    }
}
登录后复制

尽管到目前为止,课程中还没有深入讨论访问修饰符,但我选择将所有字段保留为私有,想象在银行系统中,分行、帐户、持有人和余额数据必须得到很好的保护,并且只有类本身应该可以访问它们。

此外,createAccount 方法不应该返回任何内容,而只是在控制台中显示一条消息,因此它的返回值为 void。
Java 中一些令我恼火的事情就是从这个方法开始的。用于捕获用户输入的任何类型信息的 Scanner 类没有使用通用方法来捕获用户输入的任何类型的信息,而是为每种原始类型提供特定方法。换句话说,对于字符串有 Scanner.nextLine(),对于数字有 Scanner.nextInt(),对于布尔值有 Scanner.nextBoolean...

Exercício - Simulando Uma Conta Bancária Através Do Terminal

相比之下,在 C# 中,我们有一个标准输入方法,它总是返回一个 String,然后它的类型发生变化:

String input = Console.ReadLine();
int.TryParse(input, out number)
Console.WriteLine(number) //completamente válido
登录后复制

我还需要写一点吗?他有。但至少我不需要记住所有方法的语法,只需记住一个并转换为我接下来想要的类型。更加直观。
但让我们继续吧,要解决这个问题还有很长的路要走。然后,下一步是要求用户输入客户数据进行注册。

TerminalAccount.java

public class TerminalAccount {  
    private int branch;  
    private String account;  
    private String clientName;  
    private double balance;  

    public void createAccount() {  
        Scanner sc = new Scanner(System.in);  
        System.out.print("Por favor, insira o número da agência: ");  
        this.branch = sc.nextInt();  

        System.out.print("Por favor, insira o número da conta: ");  
        this.account = sc.nextLine();  

        System.out.print("Por favor, insira o nome do cliente: ");  
        this.clientName = sc.nextLine();  

        System.out.print("Por favor, insira o saldo inicial: ");  
        this.balance = sc.nextDouble();  

        System.out.println("Olá " + this.clientName + ", obrigado por criar uma conta em nosso banco. sua agência é " + this.branch + ", conta " + this.account + " e seu saldo " + this.balance + " já está disponível para saque.");  
    }  
}
登录后复制

嗯,显然一切都很好。让我们在 main 方法中实例化这个类,看看会发生什么。

Main.java

public class Main {  
    public static void main(String[] args) {  
        TerminalAccount account = new TerminalAccount();  
        account.createAccount();  
    }  
}
登录后复制

Exercício - Simulando Uma Conta Bancária Através Do Terminal

牛?为什么帐号输入被忽略并且算法已经询问了客户的姓名?
阅读 Scanner 类的文档,它解释说它使用某种类型的字符作为分隔符将输入分解为标记,以知道在哪里停止。对于 .next() 和 .hasNext() 方法(及其变体,例如 .nextInt() 和 .hasNextInt()),分隔符是全局空格 (s+),例如空格、制表符和换行符。

该方法的作用是获取分隔符前面的标记,将其转换为指定的类型并返回该值。其余部分保留在输入缓冲区中。
好吧,到目前为止还好。问题在于,用于捕获字符串 的 .nextLine() 方法消耗了 换行符 (n),而不是丢弃它。然后,当在另一个丢弃的文件后面使用时,它会读取剩下的内容并立即结束其操作,继续执行下一行代码。

这听起来令人困惑,确实如此。我做了一个图表来帮助您理解这个流程的疯狂之处:

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Tá, e como consertamos essa lambança? Simples: adicionando um novo Scanner.nextLine() logo depois do .nextInt() para "limpar" o que sobrou. É bonito? Não, mas resolve.
Dá pra mudar o delimitador para aceitar a quebra de linha (\n ) em vez de um whitespace comum (\s+), mas isso poderia quebrar a forma com que as informações são quebradas em tokens, então é melhor deixar pra lá.

TerminalAccount.java

public class TerminalAccount {  
    private int branch;  
    private String account;  
    private String clientName;  
    private double balance;  

    public void createAccount() {  
        Scanner sc = new Scanner(System.in);  
        System.out.print("Por favor, insira o número da agência: ");  
        this.branch = sc.nextInt();  
        sc.nextLine();

        //...
    } 
}
登录后复制

Mais feio que bater na mãe.

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Beleza, funcionou. Poderíamos dizer que o exercício está completo, mas vamos por um segundo imaginar que o usuário, sem querer, digitou uma letra na hora de colocar o número da agência:

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Eita lasqueira.

Isso acontece porque, como já sabemos, a tipagem do Java é estática e o Scanner está esperando um número mas quando colocamos uma letra junto com um número, essa cadeia se torna uma String. O input que estava esperando um int recebeu uma String e ficou confuso tal qual uma criança que recebe meias de presente de natal.
Exercício - Simulando Uma Conta Bancária Através Do Terminal

Para remediar essa situação, podemos criar um loop simples, que informe para o usuário que a informação que ele inseriu está incorreta de acordo com as especificações do sistema e pedir que ele insira os dados novamente (de maneira correta, dessa vez). Como não sabemos quantas tentativas o usuário vai levar para inserir os dados corretamente, um while parece adequado.

public class TerminalAccount {  
    private int branch;  
    private String account;  
    private String clientName;  
    private double balance;  

    public void createAccount() {  
        Scanner sc = new Scanner(System.in);  

        boolean isBranchNumberInputCorrect = false;  
        do {  
            try {  
                System.out.print("Por favor, insira o número da agência: ");  
                this.branch = sc.nextInt();  
                sc.nextLine();  
                isBranchNumberInputCorrect = true;  
            } catch (InputMismatchException e) {  
                System.out.println("Por favor, insira apenas números inteiros para o número da agência."); 
                sc.nextLine(); 
            }  
        } while (!isBranchNumberInputCorrect);

        //...
    }
}
登录后复制

Aqui criamos uma variável de controle chamada IsBranchNumberInputCorrect (porque, novamente, sou muito criativo quando se trata de nomes), inicializada em false. Em seguida, começamos o bloco do, uma vez que queremos que o código faça uma ação antes de verificar se o dado inserido é valido ou não e jogamos nosso input lá pra dentro.
Caso dê tudo certo, o dado inserido será armazenado no campo branch, qualquer caractere sobrando será consumido pelo Scanner.nextLine() e a nossa variável de controle será atualizada para true. Aí a condição do while vai checar se isBranchNumberInputCorrect é false. Se for, reinicia o loop no caso de sucesso, o laço é encerrado.

Agora, caso o usuário insira algo não esperado (como uma String), o método Scanner.nextInt() vai emitir um evento de erro InputMismatchException, que será capturado pelo nosso bloco catch. Uma vez lá dentro, o código vai exibir uma mensagem de erro alertando que o tipo de dado está errado e consumido qualquer caractere que tenha ficado pra trás.

Exercício - Simulando Uma Conta Bancária Através Do Terminal

A gente pode fazer a mesma coisa com o input de saldo, para garantir que o valor inserido sempre será numérico e não permitir que a aplicação quebre caso seja inserido algo como 12,56f:

public class TerminalAccount {  
    private int branch;  
    private String account;  
    private String clientName;  
    private double balance;  

    public void createAccount() {  
        Scanner sc = new Scanner(System.in); 

        //...

        boolean isBalanceInputCorrect = false;  
        do {  
            try {  
                System.out.print("Por favor, insira o saldo inicial: ");  
                this.balance = sc.nextDouble();  
                sc.nextLine();  
                isBalanceInputCorrect = true;  
            } catch (InputMismatchException e) {  
                System.out.println("Por favor, insira apenas valores decimais.");  
                sc.nextLine();  
            }  
        } while (!isBalanceInputCorrect);  

        //...
    }  
}
登录后复制

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Poderíamos parar por aqui e dar esse exercício como encerrado, mas ainda tem um bug que requer um pouco de atenção. O que aconteceria se, em vez de delimitarmos nosso saldo com uma vírgula (,) usássemos um ponto (por exemplo, 10.56)?

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Isso acontece devido ao locale, a adaptação do input à cultura do local. Aqui no Brasil, o decimal é delimitado pela vírgula, então o método não entende que essa separação com ponto é válida.
A documentação da classe Scanner nos mostra que é possível alterar a cultura para uma que atenda ou um ou outro padrão, mas não os dois ao mesmo tempo. Também é possível alterar especificamente o delimitador, para um símbolo ou para outro, mas não os dois ao mesmo tempo.

Exercício - Simulando Uma Conta Bancária Através Do Terminal

Um dos métodos para solucionar esse problema não é muito elegante, mas resolve: em vez de capturar o dado diretamente como double, vamos usar o método Scanner.nextLine() para pegar o input como uma String, trocar os pontos por vírgula e tentar trocar o tipo para double.

public class TerminalAccount {  
    private int branch;  
    private String account;  
    private String clientName;  
    private double balance;  

    public void createAccount() {  
        Scanner sc = new Scanner(System.in);  

        //...
        boolean isBalanceInputCorrect = false;  
        do {  
            try {  
                System.out.print("Por favor, insira o saldo inicial: ");  
                String balanceString = sc.nextLine().replace(",", ".");  
                this.balance = Double.parseDouble(balanceString);  
                isBalanceInputCorrect = true;  
            } catch (NumberFormatException e) {  
                System.out.println("Por favor, insira apenas valores decimais.");  
            }  
        } while (!isBalanceInputCorrect);  

        //...

    }  
}
登录后复制

Além da alteração do método de captura do dado, tivemos mais algumas modificações: retiramos as chamadas para o método Scanner.nextLine() que serviam apenas para consumir os caracteres remanescentes, porque nosso input já faz isso pra gente. Além disso, o tipo do erro mudou: agora não se trata de um erro de incompatibilidade de tipo (InputMismatchException), mas sim um de erro no formato do número (NumberFormatException).
Com essas alterações feitas, bora ver se tudo deu certo:

Exercício - Simulando Uma Conta Bancária Através Do Terminal
Exercício - Simulando Uma Conta Bancária Através Do Terminal

Exercício - Simulando Uma Conta Bancária Através Do Terminal
Deu tudo certo! Com isso, conseguimos dizer que o exercício está concluído (finalmente)!
O repositório desse exercício está disponível aqui caso tenha interesse de ver.

E é isso. Até o próximo módulo!

以上是练习 - 使用终端模拟银行账户的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!