Вопрос о InputMismatchException при использовании сканера - PullRequest
1 голос
/ 25 апреля 2010

Вопрос:

Входной файл: номер счета клиента, остаток на счете в начало месяца, тип транзакции (вывод средств, депозит, проценты), сумма сделки

Вывод: номер счета, начальный баланс, конечный баланс, общая сумма уплаченных процентов, общая сумма депозита, количество депозиты, общая сумма снятия, количество снятий

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 ]

3 голосов
/ 25 апреля 2010

Вот как бы я поступил:

  • Посмотрите, что означает это исключение в документации API .
  • подумайте, как это могло произойти, по какой линии это происходит (посмотрите на трассировку стека). Если вы не знаете, как прочитать трассировку стека, вот учебник .
  • если вы не можете сразу увидеть причину, установите точку останова и запустите ее через отладчик, чтобы «визуализировать» текущее состояние вашей программы до возникновения исключения.

Возможно, вы еще не знаете, как использовать ваш отладчик, и хотя некоторые могут не согласиться, я думаю, что никогда не бывает слишком рано. Здесь есть несколько отличных видеоуроков о том, как использовать отладчик здесь . Удачи!

2 голосов
/ 13 сентября 2013

Я думаю, что уже слишком поздно, чтобы ответить на этот вопрос, но я недавно наткнулся на ту же проблему, и мой поиск в Google привел меня сюда.

Я думаю, что наиболее распространенным случаем для InputMismatchException, выданным Scanner.nextDouble(), является то, что используемая вашим Scanner локаль по умолчанию ожидает удвоения в другом формате (например, 10,5, а не 10.5). Если это так, вы должны использовать Scanner.useLocale метод, подобный этому

Scanner s = new Scanner(System.in);
s.useLocale(Locale.US);
1 голос
/ 25 апреля 2010

Мне не очень нравится дизайн, все в одном, поскольку он идет вразрез с сильными сторонами Java, немного ориентирован на объект. Поэтому я переписал программу так, как мне кажется.

Я также выяснил, что интерпретация двойных символов зависит от локали , на моей машине двойной (в строке) должен иметь запятую (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();
            }
        }
    }
}
1 голос
/ 25 апреля 2010

Возможно, вы захотите включить содержимое Account.in, чтобы предоставить больше информации, но вот некоторые комментарии:

Соглашения об именах

Переменные: за исключением переменных, все константы экземпляра, класса и класса находятся в смешанном регистре с строчной первой буквой .

Это означает, что по договоренности имена переменных должны быть в верхнем / нижнем регистре, например accountNum, beginningBalance, numberOfDeposits и т. Д.

Следует также отметить, что то, как вы размещаете свои фигурные скобки, очень нетрадиционно. Для вас может быть хорошей идеей изучить хороший стиль кодирования .


Эта часть также крайне противоречива:

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

Я на 99% уверен, что вам действительно нужно switch на case 1:, case 2:, case 3:.


Вы также можете распечатать конечный баланс ПОСЛЕ , который вы обработали. Прямо сейчас вы всегда будете печатать одни и те же цифры для начального и конечного баланса.

Вам также может быть полезно знать, что в Java есть операторы «составного присваивания», которые сделают ваш код более читабельным. Возможно, вам сейчас не нужно беспокоиться о точной семантике, но в основном вместо этого:

            BeginningBalance = BeginningBalance
                    + TransactionAmount;

            BeginningBalance = BeginningBalance
                    - TransactionAmount;

Вместо этого вы можете написать:

beginningBalance += transactionAmount;

beginningBalance -= transactionAmount;

Наконец, последний комментарий о InputMismatchException: другие уже объяснили вам, что это значит. Моя лучшая догадка сейчас заключается в том, что ваша проблема вызвана этим:

Входной файл: номер счета клиента, остаток на счете в начале месяца, тип транзакции (вывод, депозит, проценты), сумма транзакции

против

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

Мне нужно увидеть Account.in для подтверждения, но я подозреваю, что тип транзакции int появляется до суммы транзакции double, как сказано в заявлении о проблеме. Ваш код читает их в обратном порядке.

Это попытается прочитать int как nextDouble(), что нормально, но double как nextInt() выдаст InputMismatchException.

1 голос
/ 25 апреля 2010

Если вы читаете Exception сообщения, это InputMismatchException.Это очень вероятно вызвано функцией nextDouble() или nextInt(), когда она не читает правильный тип.Убедитесь, что ваши данные выровнены правильно, и вы не читаете двойные с readInt().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...