使用Scanner时有关InputMismatchException的问题

时间:2010-04-25 12:25:32

标签: java

问题:

输入文件:客户的帐号,帐号余额为 月初,交易类型(提款,存款, 利息),交易金额

输出帐号,期初余额,期末余额, 支付的利息总额,存款总额,数量 存款,提取的总金额,提款数量

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();
    }
}

但是给了我这个:

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

5 个答案:

答案 0 :(得分:3)

这就是我要继续下去的方式:

  • API documentation
  • 中查找Exception的含义
  • 想一想它是如何发生的,它发生了什么线(看看你的堆栈跟踪)。如果您不知道如何阅读堆栈跟踪,here's a tutorial
  • 如果您无法立即看到原因,请设置断点并通过调试器运行它,以便在异常发生之前“可视化”程序的当前状态。

您可能还不知道如何使用调试器,虽然有些人可能不同意,但我认为这永远不会太早。有一些关于如何使用调试器here的优秀视频教程。祝你好运!

答案 1 :(得分:2)

我想回答这个问题有点太晚了,但我最近偶然发现了同样的问题,我的谷歌搜索引导我来到这里。

我认为InputMismatchException引发的Scanner.nextDouble()最常见的情况是Scanner使用的默认语言环境预计会以不同的格式加倍(例如10,5,不是10.5)。如果是这种情况,您应该使用Scanner.useLocale这样的方法

Scanner s = new Scanner(System.in);
s.useLocale(Locale.US);

答案 2 :(得分:1)

如果您阅读Exception条消息,则为InputMismatchException。这很可能是由nextDouble()nextInt()函数引起的,当它没有读取正确的类型时。确保您的数据正确对齐,并且您没有使用readInt()读取双打。

答案 3 :(得分:1)

您可能希望包含Account.in的内容以提供更多信息,但以下是一些评论:

Naming conventions

  

变量:除变量外,所有实例,类和类常量都是大小写混合,带有小写的第一个字母

这意味着按照惯例,变量名称应该是大写/小写,如accountNumbeginningBalancenumberOfDeposits等。

还应该提到的是,放置花括号的方式非常不同寻常。 learn good coding style可能是个好主意。


这部分也非常不一致:

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

我99%确定您确实需要switchcase 1:case 2:上的case 3:


您可能还需要打印处理完交易的结束余额 AFTER 。现在,您将始终为开始和结束余额打印相同的数字。

知道Java具有“复合赋值”运算符可以使您的代码更具可读性,这也可能对您有所帮助。你可能现在不需要关心自己的确切语义,但基本上不是这样:

            BeginningBalance = BeginningBalance
                    + TransactionAmount;

            BeginningBalance = BeginningBalance
                    - TransactionAmount;

你可以写:

beginningBalance += transactionAmount;

beginningBalance -= transactionAmount;

最后,关于InputMismatchException的最后一条评论:其他人已经向您解释了这意味着什么。我现在最好的猜测是你的问题是由此引起的:

  

输入文件:客户的帐号,月初的帐户余额,交易类型(提款,存款,利息),交易金额

VS

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

我需要看Account.in确认,但我怀疑int交易类型出现在double交易金额之前,就像问题陈述所说的那样。您的代码以相反的顺序读取它们。

这会尝试将int读作nextDouble(),这是可以的,但doublenextInt()会抛出InputMismatchException

答案 4 :(得分:1)

我并不特别喜欢这个设计,因为它违背了Java的优点,有点面向对象。所以我按照我的想法重写了这个程序。

我还发现解释双打是依赖于语言环境,在我的机器上,double(在一个字符串中)应该有一个逗号(12,12)而不是一个点(12.12),所以可能是你的问题。

正如polygenelubricants所说,成员和方法名称在Java中较低,只有类型使用大写。

我添加了我自己的实现,不是因为你的工作不起作用,而是为了展示如何将责任委托给反映问题域的类,使代码更具可读性(尽管使用样板读取器和设置器的时间要长得多)。

我的程序实现类似于:

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();
            }
        }
    }
}