kjdhowiegf
@kjdhowiegf

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

InputMismatchException の解決方法を教えてください。

解決したいこと

解決法がわからないです

例)
Java初学者です。
aoj betaでプログラムを作っているときにInputMismatchExceptionが起きました。
ネットで調べたりほかの方の回答を参考に見させていただきましたが、このソースコードでどこがエラーの原因になっているかが分かりません。
分かる方ご教授願います、、、。
Main.javaの11行目はb=sc.nextInt()の部分です

発生している問題・エラー

Exception in thread "main" java.util.InputMismatchException at 
java.base/java.util.Scanner.throwFor(Scanner.java:939) at 
java.base/java.util.Scanner.next(Scanner.java:1594) at 
java.base/java.util.Scanner.nextInt(Scanner.java:2258) at 
java.base/java.util.Scanner.nextInt(Scanner.java:2212) at 
Main.main(Main.java:11) Command exited with non-zero status 1 0.05user 0.00system 0:00.03elapsed 168%CPU (0avgtext+0avgdata 40684maxresident)k 0inputs+72outputs (0major+3725minor)pagefaults 0swaps

例)

2つの整数 a, b と1つの演算子 op を読み込んで、a op b を計算するプログラムを作成して下さい。ただし、演算子 op は、"+"(和)、"-"(差)、"*"(積)、"/"(商)、のみとし、割り算で割り切れない場合は、小数点以下を切り捨てたものを計算結果とします。

入力は複数のデータセットから構成されています。各データセットの形式は以下のとおりです:

a op b

op が '?' のとき 入力の終わりを示します。このケースの出力は行ってはいけません。

### 該当するソースコード
```Java

	public static void main(String[] args) {
    	Scanner sc = new Scanner(System.in);
    	int a = 0;
    	int b = 0;
		while(true){
		   a = sc.nextInt();
		   b = sc.nextInt();
		  String op = sc.next();
		
	  switch(op) {
       case "+":
	    System.out.println(a+b);
	    break;
       case "-":
    	System.out.println(a-b);
	    break;
       case "*":
	    System.out.println(a*b);
	    break;
       case "/":
        System.out.println(a/b);
        break;
       default :
        sc.close();
        break;
	  }
}
}
}
0

2Answer

Scanner sc = new Scanner(System.in);が実行され、
標準入力を行う際に、2か所目に整数以外を入力したのではないですか?

例えば、「10 20 +」と入力すると意図されている動作を
するかと思いますが、「10 + 20」のように入力すると例外を吐きます。

可能性としてはa op bに惑わされて
「10 + 20」のように入力した、等。

最初の文章に
「2つの整数 a, b と1つの演算子 op を読み込んで」と記述があり、
その通りにプログラムを書いているので、
その順番で入力する必要があります。

1Like

Comments

  1. @kjdhowiegf

    Questioner

    コメントありがとうございます。

    何度も確認してみましたがここ以外に整数以外を入力した箇所は見当たりませんでした。

    またswitch文の部分のみをif(op = ?){break;}else if (op = "+"){System.out.println(a+b)}....のようにif文にしてみるとなぜか例外なく実行出来ました。

  2. 申し訳ないです。
    流し読みであった為、正確に回答し直します。

    switchステートメントのdefaultブロック内に記述してある
    breakswitchステートメントを抜けるものなので、
    whileループは続いたままになります。

    sc.clise()によってScannerがクローズされた後、
    無限ループによって、再度Scanner.nextInt()が呼び出されたタイミングで
    例外がスローされます。

    「+、-、*、/」以外が入力された場合に終了し、
    出力しない例は以下になります。
    packageは私の環境でそのようにしただけなので無視してください

    Calculator.java
    package qiita_questions;
    
    import java.util.Scanner;
    
    public class Calculator {
    
        public static void main (String[] args) {
            Scanner sc = new Scanner (System.in);
            int a = 0;
            int b = 0;
            while (true) {
                a = sc.nextInt ();
                b = sc.nextInt ();
                String op = sc.next ();
    
                switch (op) {
                    case "+":
                        System.out.println (a + b);
                        break;
                    case "-":
                        System.out.println (a - b);
                        break;
                    case "*":
                        System.out.println (a * b);
                        break;
                    case "/":
                        System.out.println (a / b);
                        break;
                    default:
                        sc.close ();
                        return;
                }
            }
        }
    }
    

    後学の為に参考になればと思い
    コメント付きの別解も書いてみたのでもしよければ読んでみてください。

    Calculator2.java
    package qiita_questions;
    
    import java.util.Scanner;
    
    public class Calculator2 {
        
        public static void main (String[] args) {
            Scanner scanner = new Scanner (System.in);
            
            while (true) {
                int a = scanner.nextInt ();
                int b = scanner.nextInt ();
                char op = scanner.next ().charAt (0);
                
                if (op == '?') {
                    // 終了
                    break;
                }
                
                int result;
                switch (op) {
                    case '+':
                        result = a + b;
                        break;
                    case '-':
                        result = a - b;
                        break;
                    case '*':
                        result = a * b;
                        break;
                    case '/':
                        result = a / b;
                        break;
                    default:
                        // 演算子が無効な場合は、不明な演算子として処理
                        System.out.println ("無効な演算子です。");
                        result = 0;
                }
                
                System.out.println (result);
            }
            
            scanner.close (); // Scannerを閉じる
        }
    }
    
  3. @kjdhowiegf

    Questioner

    回答ありがとうございます。

    なるほど!close()でScannerを閉じてからもwhileのループが終わっていませんでした!

    送っていただいたコードを参考にもう一度作り直すと無事に実行出来ました!ありがとうございました!

  4. 疑問が解消されましたら当質問のクローズをお願いします。

InputMismatchExceptionは、Scannerが読み込もうとしたデータが、期待される型と一致しない場合に発生します。

プログラムでは、2つの整数の後に演算子(文字列)が来ることを期待していますが、Scannerが整数を読み込もうとする前に文字列が入力されると、InputMismatchExceptionが発生します。

また、プログラムのロジックには別の問題があります。それは、op'?'の場合にも、abを読み込んでしまう点です。op'?'の場合、プログラムは入力の終わりを示すため、それ以上の入力(特にab)を読み込むべきではありません。

以下の修正を加えることで、これらの問題を解決できます:

  1. 演算子opを先に読み込み、それが'?'であるかどうかをチェックします。これにより、不要なabの読み込みを避けることができます。
  2. nextIntを呼び出す前にhasNextIntメソッドを使って、次の入力が整数であるかどうかを確認します。これにより、意図しない型の入力を検出し、例外を回避することができます。

修正したコードは次のようになります:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(true){
            String op = sc.next(); // 演算子を先に読み込む
            if (op.equals("?")) { // 入力の終わり
                break;
            }
            int a = sc.nextInt(); // 次に整数aを読み込む
            int b = sc.nextInt(); // 次に整数bを読み込む

            switch(op) {
                case "+":
                    System.out.println(a + b);
                    break;
                case "-":
                    System.out.println(a - b);
                    break;
                case "*":
                    System.out.println(a * b);
                    break;
                case "/":
                    System.out.println(a / b);
                    break;
            }
        }
        sc.close();
    }
}

この修正により、op'?'の場合には、それ以上何も読み込まずにループを抜け、プログラムを終了するようになります。

1Like

Comments

  1. @kjdhowiegf

    Questioner

    回答ありがとうございます。

    scannerで読むこむ型に先入観をもってしまっておりました…。すごく納得です。

    opを先に判定してからa,bを読みこんだ方が負荷がかからずいいですね…修正コードまで書いていただきありがとうございます!

Your answer might help someone💌