Rumah  >  Artikel  >  Java  >  Latihan - Mensimulasikan Akaun Bank Menggunakan Terminal

Latihan - Mensimulasikan Akaun Bank Menggunakan Terminal

PHPz
PHPzasal
2024-08-12 22:43:49347semak imbas

Untuk keluar sedikit daripada teori, langkah seterusnya dalam bootcamp ialah latihan (yang mereka panggil cabaran projek). Saya fikir ia akan menarik untuk memasukkan bahagian praktikal untuk menyatukan kandungan yang diliputi setakat ini.

Apa yang diminta ialah mencipta projek yang menyerupai satu akaun dalam bank, yang mengandungi nombor cawangan, nombor akaun, nama pelanggan dan imbangan. Data ini mesti datang dari terminal dan pada penghujungnya, mesej mesti dipaparkan yang menyatakan bahawa akaun telah berjaya dibuat dan menunjukkan data yang dimasukkan. Penerangan asal boleh dilihat di sini.

Nampaknya agak mudah. Tetapi satu perkara yang saya sangat suka lakukan dalam mana-mana tugas yang saya terima ialah memecahkannya kepada langkah-langkah yang sangat singkat, supaya saya mempunyai jalan yang jelas untuk diikuti. Saya melakukan ini juga kerana semasa saya melukis aliran dalam kepala saya, saya dapat memahami sama ada ia masuk akal dengan apa yang ditanya dan saya boleh menukar tindakan dengan cepat jika saya fikir ia tidak berkesan.

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

Oleh itu, langkah-langkah yang perlu diikuti adalah seperti berikut:

  1. Buat kelas untuk "menempatkan" data yang diterima dalam terminal dan kaedah pencipta akaun;
  2. Minta data daripada pengguna, baca maklumat yang dimasukkan ke dalam terminal dan simpan dalam pembolehubah;
  3. Tunjukkan kepada pengguna mesej pengesahan, atur pembolehubah menjadi rentetan yang boleh dibaca.

Nampaknya bukan sesuatu yang kompleks. Bermula dengan langkah 1, kami mempunyai yang berikut:

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
    }
}

Walaupun pengubah akses belum diliputi secara mendalam setakat ini dalam kursus ini, saya memilih untuk membiarkan semua medan tertutup, membayangkan bahawa dalam sistem perbankan, cawangan, akaun, pemegang dan data baki mesti dilindungi dengan baik dan hanya kelas sendiri sepatutnya mempunyai akses kepada mereka.

Selain itu, kaedah createAccount tidak seharusnya mengembalikan apa-apa, cuma paparkan mesej dalam konsol, jadi pemulangannya tidak sah.
Kaedah ini adalah di mana beberapa perkara yang menjengkelkan saya tentang Java bermula. Daripada mempunyai kaedah generik yang menangkap sebarang jenis maklumat yang dimasukkan pengguna, kelas Pengimbas, yang digunakan untuk ini, mempunyai kaedah khusus untuk setiap jenis primitif. Dalam erti kata lain, terdapat Scanner.nextLine() untuk Strings, Scanner.nextInt() untuk nombor, Scanner.nextBoolean untuk boolean...

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

Sebagai perbandingan, dalam C# kami mempunyai kaedah input standard yang sentiasa mengembalikan String, yang kemudian jenisnya ditukar:

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

Adakah saya perlu menulis lebih sedikit? Dia ada. Tetapi sekurang-kurangnya saya tidak perlu mengingati sintaks semua kaedah, hanya satu dan tukar kepada jenis yang saya mahu seterusnya. Lebih intuitif.
Tetapi mari kita teruskan, masih jauh lagi untuk menyelesaikan masalah ini. Langkah seterusnya ialah meminta pengguna memasukkan data pelanggan untuk pendaftaran.

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.");  
    }  
}

Nah, nampaknya semuanya baik-baik saja. Mari kita nyatakan kelas ini dalam kaedah utama kita dan lihat apa yang berlaku.

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

Lembu? Mengapakah input nombor akaun diabaikan dan algoritma sudah meminta nama pelanggan?
Membaca dokumentasi untuk kelas Pengimbas, dijelaskan bahawa ia memecahkan input kepada token menggunakan beberapa jenis aksara sebagai pembatas, untuk mengetahui di mana hendak berhenti. Dalam kes kaedah .next() dan .hasNext() (dan variannya, seperti .nextInt() dan .hasNextInt()), pembatas ialah ruang putih global (s+) seperti ruang, tab dan pemisah baris .

Apa yang dilakukan oleh kaedah ialah mengambil token yang didahului oleh pembatas, menukarnya kepada jenis yang ditentukan dan mengembalikan nilai tersebut. Selebihnya kekal dalam penimbal input.
Okay, setakat ni ok. Masalahnya ialah kaedah .nextLine(), yang digunakan untuk menangkap Strings menggunakan aksara pemisah baris (n), dan bukannya membuangnya. Kemudian, apabila digunakan mengikuti yang lain yang membuang, ia membaca apa yang tertinggal dan serta-merta menamatkan operasinya, beralih ke baris kod seterusnya.

Kedengarannya mengelirukan, dan memang begitu. Saya membuat rajah untuk membantu anda memahami kegilaan aliran ini:

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!

Atas ialah kandungan terperinci Latihan - Mensimulasikan Akaun Bank Menggunakan Terminal. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn