1. 程式人生 > >java的nextLine()的一個報錯引發的思考

java的nextLine()的一個報錯引發的思考

寫在最前面:

晚上幫一位同學看一段程式碼,程式碼很入門,不過是java的,還好我也是懂java的男人,哼哼

 

程式碼如下,我做了一點調整,方便看輸出:

package Arithmetic;
import java.util.Scanner;

class PayCheck
{
  public static void main(String args[])
  {
    //user's input
    Scanner kbReader = new Scanner (System.in);
    String famName;
    String givName;
    double ratePay;
    int workHour;
    char charity;
    char tax;
    System.out.println("What is your family name?");
    famName = kbReader.nextLine();
    System.out.println("What is your given name?");
    givName = kbReader.nextLine();
    System.out.println("What is your hourly rate of pay($/h)?");
    ratePay = kbReader.nextDouble();
    System.out.println("How many hours you have worked this week?");
    workHour= kbReader.nextInt();
    System.out.println("Do you want $20 deducted from the weekly pay as a contribution to chairty? Enter Y for yes and N for no.?");
    charity = kbReader.nextLine().charAt(0);
    System.out.println("What's your tax category?(choose from A to E.)");
    tax = kbReader.nextLine().charAt(0);
    
    
    
    //processing
    //Gross Pay
    double grossPay;
    if (workHour<=40)
    {
      grossPay=workHour*ratePay;
    }
    else
    {
      grossPay=40*ratePay+(workHour-40)*ratePay*2;
    }
    //Charity
    if (charity=='Y')
      grossPay=grossPay-20;
    else if(charity=='N')
      grossPay=grossPay-0;
      
  
    //Deduction
    double dedu;
    if (tax=='A')
      dedu=0;
    else if (tax=='B')
      dedu=grossPay*0.1;
    else if(tax=='C')
      dedu=grossPay*0.2;
    else if(tax=='D')
      dedu=grossPay*0.29;
    else 
      dedu=grossPay*0.35;
    
    //net pay
    double netPay;
    netPay=grossPay-dedu;
    
    //output
   System.out.println("Weekly Pay Slip");
   System.out.println(famName+givName);
   System.out.println("Gross Pay: /$"+grossPay);
   System.out.println("Deductions: /$"+dedu);
   System.out.println("Net Pay: /$"+netPay);
  }
}
    
   

這個有啥問題呢?

What is your family name?
A
What is your given name?
B
What is your hourly rate of pay($/h)?
12
How many hours you have worked this week?
6
Do you want $20 deducted from the weekly pay as a contribution to chairty? Enter Y for yes and N for no.?
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
	at java.lang.String.charAt(Unknown Source)
	at Arithmetic.PayCheck.main(PayCheck.java:25)

那麼很顯然了,第一個出錯的是這一行(不代表後面的沒問題)

charity = kbReader.nextLine().charAt(0);

我們在之前定義了一個

char charity;

由於java中沒有提供方法直接從鍵盤接收一個字元,但是我們可以用從鍵盤接收一個字串實現接收一個字元的功能,就是接收字串中第一個字元。

但是這個和報錯有什麼關係呢,明明思路沒問題啊。

當我們嘗試改成:

charity = kbReader.next().charAt(0);

就OK了

Do you want $20 deducted from the weekly pay as a contribution to chairty? Enter Y for yes and N for no.?
uu
u

那麼next()和nextLine()有什麼區別呢?

next()方法在讀取內容時,會過濾掉有效字元前面的無效字元,對輸入有效字元之前遇到的空格鍵、Tab鍵或Enter鍵等結束符,next()方法會自動將其過濾掉;只有在讀取到有效字元之後,next()方法才將其後的空格鍵、Tab鍵或Enter鍵等視為結束符;所以next()方法不能得到帶空格的字串。

nextLine()方法返回的是Enter鍵之前沒有被讀取的所有字元,它是可以得到帶空格的字串的


一句話,next()方法讀取到空白符就結束,nextLine()讀取到回車結束也就是“\r”。

 

那麼當我們試圖用nextLine()讀取字串的第一個字元時,由於我們還沒有輸入,意味著輸入會是一個空字串,而空字串的長度是0,charAt(0)時,一定會超長。

java.lang.String.charAt() 方法返回指定索引處的char值。索引範圍是從0到length() - 1。對於陣列索引,序列的第一個char值是在索引為0,索引1,依此類推。

 

當我們debug看的時候了,程式碼如下:

System.out.println("Do you want $20 deducted from the weekly pay as a contribution to chairty? Enter Y for yes and N for no.?");
    try {
    	        System.out.println("".charAt(0));
		charity = kbReader.nextLine().charAt(0); 
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

 

在這一句上加斷點:

System.out.println("".charAt(0));

 

如圖所示:

 

 我們試圖列印空字串的第一個字元,由於charAt()的定義是0到length()-1,那麼此時索引超長,直接丟擲異常。

 而next()就不會,因為遇到空格它就直接結束了。