質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

841閲覧

Scannerが使えない(に関する問題)part3

cretter

総合スコア91

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2020/10/02 04:07

前提・実現したいこと

現在classをどんどん追加して入力した番号に対応したclassを実行させるプログラムを作っているのですが、その入力にScannerを使用していてまず0を入力したところclassを選択するところはできたのですがclass calcuScannerが実行しようとした瞬間エラーが起きました。直し方を教えてください。

発生している問題・エラーメッセージ

Exception in thread "main" java.util.NoSuchElementException at java.base/java.util.Scanner.throwFor(Scanner.java:937) at java.base/java.util.Scanner.next(Scanner.java:1478) at calcu.test03(test0301.java:25) at test0301.main(test0301.java:13)

該当のソースコード

java

1import java.util.Scanner; 2 3public class test0301 4{ 5 public static void main(String[] args) 6 { 7 System.out.print(">>"); 8 var sentaku = new Scanner(System.in); 9 int cl_num = sentaku.nextInt(); 10 sentaku.close(); 11 var cl0 = new calcu(); 12 switch(cl_num){ 13 case 0:cl0.test03();break; 14 } 15 16 17 } 18} 19class calcu 20{ 21 void test03(){ 22 Scanner sc = new Scanner(System.in); 23 put("説明を表示しますか"); 24 put("Y or N"); 25 String setumei = sc.next(); 26 if(setumei.equals("Y")||setumei.equals("y")){ 27 put("これから出てくる指示の通りに入力してください"); 28 put(""); 29 } 30 try{ 31 while(true){ 32 put("数値を入力してください"); 33 System.out.print(">>"); 34 int num1 = sc.nextInt(); 35 put("演算子を入力してください"); 36 System.out.print(">>"); 37 String str1 = sc.next(); 38 put("数値を入力してください"); 39 System.out.print(">>"); 40 int num2 = sc.nextInt(); 41 int answer = 0; 42 int answer2 = 0; 43 switch(str1){ 44 case "+": 45 answer = num1 + num2; 46 put("A."+answer); 47 break; 48 case "-": 49 answer = num1 - num2; 50 put("A."+answer); 51 break; 52 case "*": 53 answer = num1 * num2; 54 put("A."+answer); 55 break; 56 case "/": 57 answer = num1 / num2; 58 answer2 = num1 % num2; 59 if(answer2 != 0){ 60 put("A."+answer + "…"+answer2); 61 }else{ 62 put("A."+answer); 63 } 64 break; 65 case ";": 66 answer = num1 + num2; 67 put("A."+answer); 68 break; 69 case ":": 70 answer = num1 * num2; 71 put("A."+answer); 72 break; 73 } 74 put(""); 75 put("もう一度計算しますか"); 76 put("Y or N"); 77 String nextln = sc.next(); 78 if(nextln.equals("Y")||nextln.equals("y")){ 79 put(""); 80 }else{ 81 put("終了します"); 82 break; 83 } 84 } 85 } 86 catch(Exception e){ 87 put("終了します"); 88 } 89 sc.close(); 90 } 91 public static void put(String str) 92 { 93 System.out.println(str); 94 } 95}

補足情報(FW/ツールのバージョンなど)

java jdk-14.0.2

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

System.in は Scanner で close すると、もう使えなくなります。
new Scanner(System.in) とその close はプログラム中で一度だけにしましょう。

diff

1- sentaku.close(); 2- var cl0 = new calcu(); 3+ var cl0 = new calcu(sentaku); 4 switch(cl_num){ 5 case 0:cl0.test03();break; 6 } 7- 8- 9+ sentaku.close(); 10 } 11 } 12 class calcu 13 { 14+ Scanner sc; 15+ calcu(Scanner sc) { this.sc = sc; } 16 void test03(){ 17- Scanner sc = new Scanner(System.in); 18 put("説明を表示しますか"); 19 } 20- sc.close(); 21 }

追記

close(); を一度使うと二度と Scanner を使えなくなるという認識で正しいでしょうか。

System.in に関してはそうです。
他のファイルや文字列に対しては、Scanner は何度でも使えます。

System.in に関しても close() しなければ何度でも使えますが、
new するたびにバッファが確保され、リソースが無駄になります。

まず、次のコードを試してみてください。

Java

1import java.util.Scanner; 2 3class Test { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 if (!sc.hasNextLine()) { 7 System.out.println("1. no line"); 8 return; 9 } 10 String line = sc.nextLine(); 11 System.out.println(line); 12 sc.close(); 13 14 sc = new Scanner(System.in); 15 if (!sc.hasNextLine()) { 16 System.out.println("2. no line"); 17 return; 18 } 19 line = sc.nextLine(); 20 System.out.println(line); 21 sc.close(); 22 } 23}

2回目の new Scanner(System.in); はエラーになります。

では、最初の sc.close(); を実行しなければどうなるか?
キーボード入力で 2行読めます。

ところが、java Test <file.txt のように標準入力をファイルに切り替えると
2行目の読み込みができません。

なぜかというと、Scanner は内部にバッファ(多分 8KB)を用意します。

入力がキーボードだと、1回の read で、1行しかバッファに読み込まないため、
新しい Scanner でも次の行が読めます。

でも、入力がファイルだと、最初の Scanner がファイルを読み込めるだけ全部
バッファに読み込んでしまいます。
次の Scanner はもう読み込むものがありません。
ファイルのサイズが 8KB 以上だったら、続きが読めます。
でも、2行目は最初の Scanner で読み込まれているので、
ずっと後の行の途中からしか読み込めません。

投稿2020/10/02 12:54

編集2020/10/02 14:39
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cretter

2020/10/02 14:04 編集

close(); を一度使うと二度と Scanner を使えなくなるという認識で正しいでしょうか。
cretter

2020/10/06 13:05

追伸ありがとうございます。 とても分かりやすかったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問