天天看點

使用Scanner循環輸入并校驗時出現的問題問題一:循環建立Scanner對象并使用close()方法問題二:循環輸入校驗時不處理校驗失敗的部分其他用法

目錄

  • 問題一:循環建立Scanner對象并使用close()方法
  • 問題二:循環輸入校驗時不處理校驗失敗的部分
  • 其他用法

問題一:循環建立Scanner對象并使用close()方法

菜鳥想要用Scanner達到循環輸入的目的,沒有直接百度而是“自以為是”的在循環裡寫建立Scanner類,并且還“體貼”的在使用完畢後close()掉:

for(int i = 0; i < 3; i++) {
			System.out.println("第"+(i+1)+"次輸入");
			Scanner sc = new Scanner(System.in);
			String strInput = sc.next();
			sc.close();
		}
           

然而,在循環到第二次的時候就不對了:

使用Scanner循環輸入并校驗時出現的問題問題一:循環建立Scanner對象并使用close()方法問題二:循環輸入校驗時不處理校驗失敗的部分其他用法

試了半天,最後老實問度娘:Scanner + java.util.NoSuchElementException

原來是因為第二次循環sc.next()找不到下一個元素,找不到的原因是因為上次循環結束時關閉了System.in。

“System.in 在java中是靜态變量,目前類所有的scanner對象共享它,當一個scanner對象執行close()操作後,其他所有的scanner對象都不可用了。”

—— Scanner 的執行錯誤NoSuchElementException

正确姿勢:

Scanner sc = new Scanner(System.in);
		for(int i = 0; i < 3; i++) {
			System.out.println("第"+(i+1)+"次輸入");
			String strInput = sc.next();
		}
		sc.close();
           

把開頭結尾丢循環外面就對了~

問題二:循環輸入校驗時不處理校驗失敗的部分

之是以要循環輸入是因為想要做校驗,輸入不通過就繼續輸入。比如:判斷輸入的類型;輸入是否在規定範圍内等。

判斷輸入的類型可以用Scanner的hasNextInt()、hasNextDouble()等,其中hasNext()就是判斷是否有下一次輸入的内容,不管類型,其他的都是判斷是否有下一個相應類型的輸入。比如輸入一個整數:

Scanner sc = new Scanner(System.in);
		while(true) {
			System.out.println("請輸入一個整數:");
			if(sc.hasNextInt()) {
				int intInput = sc.nextInt();
				System.out.println("輸入的整數為:"+intInput);
				break;
			}
		}
		sc.close();
           

問題不是有值怎樣,而是沒有值怎麼處理,如果輸入的是"abc",我以為的結果是接着下一次輸入就好了,然而事實是:

使用Scanner循環輸入并校驗時出現的問題問題一:循環建立Scanner對象并使用close()方法問題二:循環輸入校驗時不處理校驗失敗的部分其他用法

進入了死循環…我在sc.hasNextInt()那行打了斷點,發現進入if之後,第一次程式會等待我輸入内容,後面就不等我輸入了,直接判斷不符合if條件。

“遇到hasNext()時,Scanner也會阻塞,等待你輸入,等你輸入後傳回true。檢視jdkapi,你會發現該方法當Scanner緩存區中有值可讀時,會傳回true,若沒有,會一直阻塞等待你輸入。”

“hasNextInt()函數大體意思表示scanner目前的标記的輸入是否為int,并不會自動的移動标記。”

——《Scanner的hasNext、hasNextInt用法》

也就是說,若輸入的是整數,進入if代碼塊,執行了hasNextInt()方法會改變讀取的标記位置;若輸入的不是整數,沒有執行類似hasNext()之類的方法,緩存區裡将會放着上次的輸入内容,進而一直if條件不滿足。

解決方法就是:hasNext()之類的方法,要和next()之類的方法搭配使用:

Scanner sc = new Scanner(System.in);
		while(true) {
			System.out.println("請輸入一個整數:");
			if(sc.hasNextInt()) {
				int intInput = sc.nextInt();
				System.out.println("輸入的整數為:"+intInput);
				break;
			}else {
				sc.next();
			}
		}
		sc.close();
           
使用Scanner循環輸入并校驗時出現的問題問題一:循環建立Scanner對象并使用close()方法問題二:循環輸入校驗時不處理校驗失敗的部分其他用法

其他用法

  1. 終止輸入:要麼在控制台 ctrl+z,要麼約定一個輸入的字元串作為終止符,寫在循環條件裡
  2. 實際上每行輸入結尾應該都帶着"\n",通過nextInt()、nextDouble()等隻能讀取數值,是不包含那個回車的,這時候再接一個nextLine()你将成功擷取到一個回車~
  3. next()方法由第一個有效字元(非空格,非換行符) 開始,到第一個分隔符或結束符(空格或換行符) 結束,進而獲得第一個掃描到的不含空格、換行符的單個字元串。換言之,如果想要擷取帶空格的内容,就用nextLine()
  4. 關于光标cursor位置:

    nextInt() - 光标位置在數值後面,"\n"前面;

    next() - 光标指向本行;

    nextLine() - 光标指向下一行