tags:

views:

80

answers:

4

The question :

Input file: customer’s account number, account balance at beginning of month, transaction type (withdrawal, deposit, interest), transaction amount

Output: account number, beginning balance, ending balance, total interest paid, total amount deposited, number of deposits, total amount withdrawn, number of withdrawals

package sentinel;

import java.io.*;
import java.util.*;

public class Ex7 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws FileNotFoundException
 {
        int AccountNum;
        double BeginningBalance;
        double TransactionAmount;
        int TransactionType;
        double AmountDeposited=0;
        int NumberOfDeposits=0;
        double InterestPaid=0.0;
        double AmountWithdrawn=0.0;
        int NumberOfWithdrawals=0;
        boolean found= false;

        Scanner inFile = new Scanner(new FileReader("Account.in"));
        PrintWriter outFile = new PrintWriter("Account.out");

           AccountNum = inFile.nextInt();
           BeginningBalance= inFile.nextDouble();

           while (inFile.hasNext())
        {
               TransactionAmount=inFile.nextDouble();
               TransactionType=inFile.nextInt();
                outFile.printf("Account Number: %d%n", AccountNum);
                outFile.printf("Beginning Balance: $%.2f %n",BeginningBalance);
                outFile.printf("Ending Balance: $%.2f %n",BeginningBalance);
                outFile.println();
               switch (TransactionType)
            {
                   case '1': // case 1 if we have a Deposite
                BeginningBalance = BeginningBalance
                        + TransactionAmount;
                AmountDeposited = AmountDeposited
                        + TransactionAmount;
                NumberOfDeposits++;
                outFile.printf("Amount Deposited: $%.2f %n",AmountDeposited);
                outFile.printf("Number of Deposits: %d%n",NumberOfDeposits);
                outFile.println();

                break;
                   case '2':// case 2 if we have an Interest
                BeginningBalance = BeginningBalance
                        + TransactionAmount;
                InterestPaid = InterestPaid
                        + TransactionAmount;
                outFile.printf("Interest Paid: $%.2f %n",InterestPaid);
                outFile.println();

                break;

                   case '3':// case 3 if we have a Withdraw
                BeginningBalance = BeginningBalance
                        - TransactionAmount;
                AmountWithdrawn = AmountWithdrawn
                        + TransactionAmount;
                NumberOfWithdrawals++;
                outFile.printf("Amount Withdrawn: $%.2f %n",AmountWithdrawn);
                outFile.printf("Number of Withdrawals: %d%n",NumberOfWithdrawals);
                outFile.println();

                    break;

                default:
                System.out.println("Invalid transaction Tybe: " + TransactionType
                        + TransactionAmount);

               }
           }
           inFile.close();
           outFile.close();
    }
}

But is gives me this :

Exception in thread "main" java.util.InputMismatchException
        at java.util.Scanner.throwFor(Scanner.java:840)
        at java.util.Scanner.next(Scanner.java:1461)
        at java.util.Scanner.nextInt(Scanner.java:2091)
        at java.util.Scanner.nextInt(Scanner.java:2050)
        at sentinel.Ex7.main(Ex7.java:36)
Java Result: 1
+1  A: 

If you read the Exception messages, it's an InputMismatchException. This is highly likely caused by the nextDouble() or nextInt() function, when it's not reading the correct type. Make sure your data is aligned correctly, and you're not reading doubles with readInt().

Xavier Ho
+1  A: 

You may want to include the content of Account.in to provide more information, but here are some comments:

Naming conventions

Variables: Except for variables, all instance, class, and class constants are in mixed case with a lowercase first letter.

This means that by convention, the variable names should be upper/lower-cased like accountNum, beginningBalance, numberOfDeposits, etc.

It should also be mentioned that the way you're placing your curly braces are highly unconventional. It may be a good idea for you to learn good coding style.


This part is also highly inconsistent:

int TransactionType; // declared as int
//...
TransactionType=inFile.nextInt(); // read as int
//...
switch (TransactionType)
   case '1': // used as ... char? ASCII '1' = 49

I'm 99% certain that you really need to switch on case 1:, case 2:, case 3: instead.


You may also want to print the ending balance AFTER you processed the transaction. Right now, you'll always print the same numbers for beginning and ending balance.

It may also benefit you to know that Java has "compound assignment" operators that would make your code a lot more readable. You probably need not concern yourself with the exact semantics right now, but basically instead of this:

            BeginningBalance = BeginningBalance
                    + TransactionAmount;

            BeginningBalance = BeginningBalance
                    - TransactionAmount;

You can instead write:

beginningBalance += transactionAmount;

beginningBalance -= transactionAmount;

Finally, one last comment about the InputMismatchException: others have already explained to you what this means. My best guess right now is that your problem is caused by this:

Input file: customer’s account number, account balance at beginning of month, transaction type (withdrawal, deposit, interest), transaction amount

vs:

           TransactionAmount=inFile.nextDouble();
           TransactionType=inFile.nextInt();

I need to see Account.in to confirm, but I suspect that the int transaction type appears before the double transaction amount, just like the problem statement says. Your code reads them in the opposite order.

This would attempt to read the int as nextDouble(), which is okay, but the double as nextInt() would throw InputMismatchException.

polygenelubricants
This my first time to study java >>> I did not know how to organize the ( Account.in) file. I did it like this: (((467343 10000.00 250.00 1 1200.00 2 75.00 2 375.00 3 100.00 2)))
@aser: it looks like `Account.in` has `double int` for `amount type`, so that order is fine. You definitely want to `switch` on `case 1:` instead of `case '1':`, though. I'd suggest debugging, either with an integrated step-through, or just putting lots of `System.out.println` statements, e.g. each time you read something from input, print to the screen what it was. That way you know _when_ the exception is thrown, and hopefully localize the problem and fix it.
polygenelubricants
+2  A: 

This is how I would proceed:

  • look up what that Exception means in the API documentation.
  • think of how it could happen, what line it happens on (look at your stack trace). If you don't know how to read the stacktrace, here's a tutorial.
  • if you can't immediately see the reason, set a breakpoint and run it through your debugger to "visualize" the current state of your program before the exception happens.

You might not know how to use your debugger yet, and while some might not agree, I think it's never too early. There are some excellent video tutorials on how to use the debugger here. Good luck!

JRL
+1  A: 

I don't particularly like the design, all in one, as it goes against the strengths of Java, a bit of object orientation. So I rewrote the program along the lines I think.

I also figured out that interpreting doubles is locale dependent, on my machine a double (in a string) should have a comma (12,12) and not a point (12.12), so that may be your problem.

And as said by polygenelubricants, member and method names are lower cased in Java, only types use Capitalization.

I added my own implementation not because yours didn't work, but to show how you could delegate responsibilities to classes which reflect the problem domain, making the code a bit more readable (though considerably longer with boilerplate getters and setters).

My implementation of your program would be something like:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.Scanner;

public class Ex7 {
    /**
     * One transaction record in the file Should be format "int double\n"
     * Note that interpreting a double is locale dependent, on my machine
     * I need "12,24" whereas a US locale might require "12.24"
     */
    public static class Transaction {
        double amount;
        int type; // Prefer an enum here...

        public void read(Scanner scanner) {
            setAmount(scanner.nextDouble());
            setType(scanner.nextInt());
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

        public double getAmount() {
            return amount;
        }

        public void setAmount(double amount) {
            this.amount = amount;
        }

        @Override
        public String toString() {
            return String.format("Transaction(type=%d, amount=%.2f)", type, amount);
        }
    }

    /**
     * Account information and processing Account file format: Line 1
     * "int double\n" account number start balance Line 2-... "double int\n"
     * transaction amount transaction type.
     * Type 1=deposit, 2=interest
     * 3=withdrawal
     */
    public static class Account {
        int accountNum;
        double startBalance;
        double currentBalance;
        double totalDeposited;
        double totalWithdrawn;
        double totalInterestPaid;
        int numberOfDeposits;
        int numberOfWithdrawals;
        int numberOfInterestPayments;

        public Account(Scanner scanner) {
            read(scanner);
        }

        private void read(Scanner scanner) {
            setAccountNum(scanner.nextInt());
            setStartBalance(scanner.nextDouble());
            setCurrentBalance(getStartBalance());
        }

        public int getAccountNum() {
            return accountNum;
        }

        public void setAccountNum(int accountNum) {
            this.accountNum = accountNum;
        }

        public double getStartBalance() {
            return startBalance;
        }

        public void setStartBalance(double startBalance) {
            this.startBalance = startBalance;
        }

        public double getCurrentBalance() {
            return currentBalance;
        }

        public void setCurrentBalance(double currentBalance) {
            this.currentBalance = currentBalance;
        }

        public void processTransaction(Transaction transaction) {
            switch (transaction.getType()) {
            case 1:
                handleDeposit(transaction.getAmount());
                break;
            case 2: // Isn't this just a deposit?
                handleInterest(transaction.getAmount());
                break;
            case 3:
                handleWithdraw(transaction.getAmount());
                break;
            default:
                throw new RuntimeException("Can not process transaction " + transaction + ", transaction type unknown.");
            }
        }

        private void handleDeposit(double deposit) {
            numberOfDeposits++;
            currentBalance += deposit;
            totalDeposited += deposit;
        }

        private void handleInterest(double interestPaid) {
            numberOfInterestPayments++;
            currentBalance += interestPaid;
            totalInterestPaid += interestPaid;
        }

        private void handleWithdraw(double amountWithdrawn) {
            numberOfWithdrawals++;
            currentBalance -= amountWithdrawn;
            totalWithdrawn += amountWithdrawn;
        }

        public String getOverview() {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("Total Deposited : " + totalDeposited).append("\n");
            stringBuilder.append("Total Withdrawn : " + totalWithdrawn).append("\n");
            stringBuilder.append("Total Interest  : " + totalInterestPaid).append("\n");
            stringBuilder.append("Current Balance : " + currentBalance).append("\n").append("\n");
            return stringBuilder.toString();
        }

    }

    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String[] args) throws FileNotFoundException {

        Scanner inFile = null;
        PrintWriter outFile= null;
        try {
            inFile = new Scanner(new FileReader("Account.in"));
            outFile = new PrintWriter("Account.out");

            Account account;
            try {
                account = new Account(inFile);
            } catch (RuntimeException e) {
                // Catch exception for error message display
                System.err.println("Could not read account information from file. Quitting");
                System.exit(1);
                return; // Otherwise compiler error :)
            }

            int lineNumber = 1; // Start with 1 because first line has account info
            while (inFile.hasNext()) {
                Transaction transaction = new Transaction();
                try {
                    transaction.read(inFile);
                } catch (RuntimeException e) {
                    System.err.println("An error ocurred while processing a transaction on line " + lineNumber + ". Transaction " + transaction + " incomplete and failed");
                    throw e; // rethrow and let the stack trace shine!
                }
                lineNumber++;

                outFile.printf("Account Number: %d%n", account.getAccountNum());
                outFile.printf("Beginning Balance: $%.2f %n", account.getStartBalance());
                outFile.printf("Current Balance: $%.2f %n", account.getCurrentBalance());
                outFile.println();

                account.processTransaction(transaction);
                outFile.print(account.getOverview());

            }
        } finally {
            if (inFile != null) {
                inFile.close(); // This can also yield an exception, but I just don't care anymore :)
            }
            if (outFile != null) {
                outFile.close();
            }
        }
    }
}
extraneon
Thanks for you efforts, but it have to be done by switch and while and if loops. I did not take a lot of things in you solution.
@aser No problem. I realize it looks like overkill. I normally work with Java code in the many thousands of lines, which needs to be maintained and extended over many years. It forces a different way of design :)
extraneon