ホームページ >Java >&#&チュートリアル >演習 - 端末を使用した銀行口座のシミュレーション
理論から少し外れますが、ブートキャンプの次のステップは演習です (これをプロジェクト チャレンジと呼んでいます)。これまで取り上げた内容を統合するための実践的な部分を含めることは興味深いのではないかと考えました。
要求されたのは、支店番号、口座番号、顧客名、バランス。このデータは端末から取得する必要があり、最後に、アカウントが正常に作成されたことを示し、どのようなデータが入力されたかを示すメッセージが表示される必要があります。元の説明はここでご覧いただけます。
そうですね、それは非常に簡単なようです。しかし、私が受けたどんな仕事でもやりたいと思っていることの 1 つは、それを非常に短いステップに分割して、従うべき道を明確にすることです。これは、頭の中で流れを描いているときに、聞かれたことと意味が合っているかどうかが分かり、ダメだと思ったらすぐに方針を変更できるからでもあります。
したがって、従うべき手順は次のとおりです:
ターミナルアカウント.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 メソッドは何も返さず、コンソールにメッセージを表示するだけであるため、その戻り値は無効です。
このメソッドは、Java に関して私がイライラするいくつかの点の始まりです。ユーザーが入力したあらゆる種類の情報を取得する汎用メソッドを持たせる代わりに、これに使用される Scanner クラスには
各プリミティブ タイプに固有のメソッドがあります。言い換えれば、文字列には Scanner.nextLine()、数値には Scanner.nextInt()、ブール値には Scanner.nextBoolean があります...
それに比べて、C# には、常に String を返し、その型が変更される標準入力メソッドがあります。
String input = Console.ReadLine(); int.TryParse(input, out number) Console.WriteLine(number) //completamente válidoもう少し書かないといけないでしょうか?彼はそうしている。ただし、少なくともすべてのメソッドの構文を覚える必要はなく、1 つだけ覚えて、次に必要な型に変換するだけです。はるかに直感的です。
しかし、続けましょう。この問題を解決するにはまだ長い道のりがあります。次のステップは、ユーザーに登録用の顧客データの入力を求めることです。
ターミナルアカウント.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(); } }
牛?口座番号の入力が無視され、アルゴリズムがすでに顧客の名前を要求しているのはなぜですか?
Scanner クラスのドキュメントを読むと、どこで停止するかを知るために、ある種の文字を区切り文字として使用して入力をトークンに分割すると説明されています。 .next() メソッドと .hasNext() メソッド (および .nextInt() や .hasNextInt() などのそのバリアント) の場合、区切り文字はスペース、タブ、改行などのグローバル ホワイトスペース (s+) です。 。
さて、ここまでは大丈夫です。問題は、文字列
をキャプチャするために使用される .nextLine() メソッドが、改行文字 (n) を破棄する代わりに を消費することです。次に、破棄する別のコマンドの後に使用すると、残されたものを読み取り、すぐに操作を終了し、コードの次の行に進みます。
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.
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:
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.
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.
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); //... } }
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)?
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.
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:
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 中国語 Web サイトの他の関連記事を参照してください。