JAVA學習【5】String數組輸入,及nextLine()、nextInt()、next()區別

       JAVA從鍵盤輸入數據時,一般可採用BufferedReader類或者Scanner類。由於Scanner類的方法更加靈活多樣,得到了更多的應用。

       最近刷題遇到String數組輸入的情況,發現Scanner方法nextLine()、next()、nextInt()的一些區別。要求先輸入一個正整數n,然後輸入n個字符串,代碼如下:

import java.util.Scanner;
public class MyCode2{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n=0;
		while(sc.hasNext()){
			n = sc.nextInt();
			String[] s = new String[n];
			int count=0;

			while(count<n){
				s[count] = sc.nextLine();
				System.out.println("s["+count+"]:"+s[count]);
				count++;
			}
		}
	}
}

運行結果如下(每次輸入完都以回車鍵結束):

       

       如果輸入n後,先空格然後輸入s[0],則得到以下結果:

       

       注意:第一個輸入的字符串是“ abc”,有一個空格

       輸入時,先調用nextInt()函數輸入n,然後回車,再調用nextLine()函數依次輸入String,結果第一個字符串自動被賦值,即第一次調用nextLine()函數返回的值並不是從鍵盤輸入的值,而是讀入的回車。

       若將數組s定義爲int類型數組,輸入都是調用nextInt()函數,則不存在此問題,運行結果如下:

       

       查詢JAVA SE 8.0 API文檔,說明如下:

       A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values of different types using the various next methods.

       

       可知,nextLine()掃描當前行,遇到回車後返回回車前的字符串,不包括末尾的換行符。nextInt()將輸入的下一個標記返回爲一個int數據,而標記指分隔符(相鄰空格或者回車)之間的字符串(不包括分隔符)。

       查詢JDK源碼,應該是nextLine()中clearCaches()清空了緩衝區,而nextInt()/next()/nextFloat()等不會清空緩存,只是讀取了相鄰分隔符之間的字符串,將分隔符仍然留在緩衝區

       因此,在前面的程序裏,先調用nextInt()再調用nextLine()函數,當輸入過程爲“3->回車->....”,第一個回車後程序不等你輸入而直接輸出“s[0]:”,因爲nextLine()首先讀到的是上次輸入遺留在緩衝區裏的第一個回車,然後直接返回空。當輸入過程爲“3->空格->abc->回車->dfg....”,nextLine()返回的是“空格abc”。

       爲了防止這類問題出現,可以在第一次調用nextLine()輸入字符串調用一次nextLine()清除緩存,即

import java.util.Scanner;
public class MyCode2{
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n=0;
		while(sc.hasNext()){
			n = sc.nextInt();
			String[] s = new String[n];
			int count=0;

			sc.nextLine();
			while(count<n){
				s[count] = sc.nextLine();
				System.out.println("s["+count+"]:"+s[count]);
				count++;
			}
		}
	}
}

       next()與nextInt()相似,也是返回相鄰分隔符之間的字符串,因此無法返回帶空格的句子。

       還有一點需要注意的是,next()、nextInt()等輸入的時候必須是完整的標記,即緩衝區必須有“分隔符+數據+分隔符”,才能把數據返回,若數據爲空,則一直等待輸入,即只按空格或回車next()、nextInt()無法返回空數據。而nextLine()只要緩衝區有回車,即可以返回空數據。


       JDK相關源碼如下:

/**
     * Advances this scanner past the current line and returns the input
     * that was skipped.
     *
     * This method returns the rest of the current line, excluding any line
     * separator at the end. The position is set to the beginning of the next
     * line.
     *
     * <p>Since this method continues to search through the input looking
     * for a line separator, it may buffer all of the input searching for
     * the line to skip if no line separators are present.
     *
     * @return the line that was skipped
     * @throws NoSuchElementException if no line was found
     * @throws IllegalStateException if this scanner is closed
     */
    public String nextLine() {
        if (hasNextPattern == linePattern())
            return getCachedResult();
        clearCaches();

        String result = findWithinHorizon(linePattern, 0);
        if (result == null)
            throw new NoSuchElementException("No line found");
        MatchResult mr = this.match();
        String lineSep = mr.group(1);
        if (lineSep != null)
            result = result.substring(0, result.length() - lineSep.length());
        if (result == null)
            throw new NoSuchElementException();
        else
            return result;
    }
/**
     * Scans the next token of the input as an <tt>int</tt>.
     *
     * <p> An invocation of this method of the form
     * <tt>nextInt()</tt> behaves in exactly the same way as the
     * invocation <tt>nextInt(radix)</tt>, where <code>radix</code>
     * is the default radix of this scanner.
     *
     * @return the <tt>int</tt> scanned from the input
     * @throws InputMismatchException
     *         if the next token does not match the <i>Integer</i>
     *         regular expression, or is out of range
     * @throws NoSuchElementException if input is exhausted
     * @throws IllegalStateException if this scanner is closed
     */
    public int nextInt() {
        return nextInt(defaultRadix);
    }


    /**
     * Scans the next token of the input as an <tt>int</tt>.
     * This method will throw <code>InputMismatchException</code>
     * if the next token cannot be translated into a valid int value as
     * described below. If the translation is successful, the scanner advances
     * past the input that matched.
     *
     * <p> If the next token matches the <a
     * href="#Integer-regex"><i>Integer</i></a> regular expression defined
     * above then the token is converted into an <tt>int</tt> value as if by
     * removing all locale specific prefixes, group separators, and locale
     * specific suffixes, then mapping non-ASCII digits into ASCII
     * digits via {@link Character#digit Character.digit}, prepending a
     * negative sign (-) if the locale specific negative prefixes and suffixes
     * were present, and passing the resulting string to
     * {@link Integer#parseInt(String, int) Integer.parseInt} with the
     * specified radix.
     *
     * @param radix the radix used to interpret the token as an int value
     * @return the <tt>int</tt> scanned from the input
     * @throws InputMismatchException
     *         if the next token does not match the <i>Integer</i>
     *         regular expression, or is out of range
     * @throws NoSuchElementException if input is exhausted
     * @throws IllegalStateException if this scanner is closed
     */
    public int nextInt(int radix) {
        // Check cached result
        if ((typeCache != null) && (typeCache instanceof Integer)
            && this.radix == radix) {
            int val = ((Integer)typeCache).intValue();
            useTypeCache();
            return val;
        }
        setRadix(radix);
        clearCaches();
        // Search for next int
        try {
            String s = next(integerPattern());
            if (matcher.group(SIMPLE_GROUP_INDEX) == null)
                s = processIntegerToken(s);
            return Integer.parseInt(s, radix);
        } catch (NumberFormatException nfe) {
            position = matcher.start(); // don't skip bad token
            throw new InputMismatchException(nfe.getMessage());
        }
    }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章