2012-10-31 60 views
3

我試圖從控制檯輸入使用in.nextLine()解析字符並從那裏取charAt(0)。我的問題是在要求用戶輸入一個字符串來執行in.nextLine()之後,它跳過輸入並由於嘗試獲取空字符串的第一個字符而產生錯誤。Java:控制檯跳過輸入

System.out.print("Select an operator (+, -, *, /), 'c' or 'C' to clear, or 'q' to quit: "); 
String temp = in.nextLine(); 
char tempOperator = temp.charAt(0); 

誤差

java.lang.StringIndexOutOfBoundsException: String index out of range: 0 
at java.lang.String.charAt(Unknown Source) 

全程序可here

一般性意見和建議,隨時歡迎。 在此先感謝。

回答

4

當您執行cValue = in.nextDouble();時,它會讀取下一個標記(完整值)並將其解析爲雙倍。如果此時按下返回鍵,則\n是要讀取的緩衝區中的下一個標記。

當你這樣做:String temp = in.nextLine();,它從以前的緩衝輸入讀取\ncharAt(0)失敗,因爲它已經只讀空(「」)的字符串。

爲了克服這個問題,或者通過加入另外in.nextLine()跳過前一緩衝器,添加\n \r作爲跳過模式如以下(這是Scanner.class定義爲LINE_SEPARATOR_PATTERN圖案):

in.skip("\r\n|[\n\r\u2028\u2029\u0085]"); 

或把一個小while循環如下:

String temp = ""; 
    while((temp.length() < 0){ 
     temp = in.nextLine(); 
    } 
+0

我希望我有15個代表,所以我可以向你投票。感謝您解釋,而不僅僅是提供解決方案。你介意解釋爲什麼while循環會比使用額外的in.nextLine()更好嗎? – zerodeficit

+0

爲什麼你需要while循環? –

+0

@zerodeficit:我更喜歡while循環,因爲用戶在輸入第一個輸入後可能會多次按下返回鍵。該循環像以前一樣保護您免受異常,直到程序沒有收到真正的輸入。 –

0

看着你的程序,這是因爲String temp = in.nextLine();。當用戶點擊「Enter」鍵時,它實質上是跳過這個語句,因爲用戶輸入了「Enter」。嘗試以下操作。請注意,我只加了下面的行,你可能會考慮String enter = in.nextLine();

import java.util.Scanner; 

public class Calculator 
{  
    public static void main(String[] args) 
    { 
     Scanner in = new Scanner(System.in); 
     char operator = 'z'; //initialize operator 
     double cValue; //current value 
     double rhValue; //right hand value 
     boolean cont = true; 

     System.out.print("Enter starting value: "); 
     cValue = in.nextDouble(); 

     // disregard the "Enter" key 
     String enter = in.nextLine(); 

     while(true) 
     { 
      System.out.print("Select an operator (+, -, *, /), 'c' or 'C' to clear, or 'q' to quit: "); 
      String temp = in.nextLine(); 
      char tempOperator = temp.charAt(0); 

      if (tempOperator == 'c' || tempOperator == 'C') 
      { 
       cValue = 0.0; 
       System.out.println("Current value is: " + cValue); 
       System.out.println(); 
      } 
      else if(tempOperator == 'q') 
      { 
       System.out.println("Final result: " + cValue); 
       System.exit(1); 
      } 
      else if(tempOperator == '+' || tempOperator == '-' || tempOperator == '*' || tempOperator == '/') 
      { 
       operator = tempOperator; 
       break; 
      } 
      else 
       throw new IllegalArgumentException("operator not valid"); 
     } 


     System.out.println("Enter a right hand value (type double): "); 
     rhValue = in.nextDouble(); 

     System.out.println("Math expression: answer " + operator + "= " + rhValue); 
     switch(operator) 
     { 
      case '+': cValue =+ rhValue; 
         break; 
      case '-': cValue =- rhValue; 
         break; 
      case '*': cValue = cValue * rhValue; 
         break; 
      case '/': cValue = cValue/rhValue; 
         break; 
     } 

     System.out.println("Current value is: " + cValue); 
    } 
} 
+0

但你沒有給出理由,當用戶點擊Enter時爲什麼會跳過該行。這就是整個問題。無論如何用戶會輸入正確的? –

+0

@RohitJain如果您查看JavaDoc for Scanner,它會聲明nextLine()「將此掃描器推進到當前行之後並返回跳過的輸入。」剛剛輸入第一個雙精度值之後,正在按下的Enter鍵強制新的一行。希望這可以幫助。 – tjg184

+0

@ tjg184 ..有點在賽道上,但不完全正確。 –

1

一件事是不是這樣做:

String temp = in.nextLine(); 

這樣做:

String temp = in.next(); 

當然,這是假設你只需要用戶輸入中的單個字符,它看起來就是你要求用戶輸入的全部字符。這將擺脫您收到的異常。但是,如果您希望在用戶鍵入多個字符時拋出錯誤,則可能需要先閱讀整行以查看長度。

1

好了,問題是在該行in.nextDouble()

Scanner#nextDouble從用戶讀取下一個標記爲double。因此,當您傳遞值4.5作爲輸入時,nextDouble只讀取令牌4.5,並在用戶輸入該輸入後跳過linefeed。現在這個換行(因爲這是一個新行),將被視爲下一個Scanner.nextLine的輸入。因此,您的in.nextLinein.nextDouble正在讀取之前in.nextDouble遺留的newline

所以,解決方法是相同的,@ tjg184在他的答案中指出。在in.nextDouble之後添加一個空的in.nextLine,它將讀取剩餘的newline。所以,你即將到來的in.nextLine讀取實際傳遞的輸入。

cValue = in.nextDouble(); 
in.nextLine(); // Add this before your `while` which will read your `newline` 

while (true) { 
    //continue; 
} 

Scanner.nextLine將讀取完整的輸入直到換行。因此,用戶下次閱讀時不會留下任何newline

雖然這個答案不需要,因爲@tjg184's答案也是一樣的。我只是添加它以更好地解釋究竟發生了什麼。

+0

很好的解釋 – tjg184

+0

@ tjg184。謝謝 :)。你的回答也是正確的。但我添加了這個答案只是爲了更清楚一點。 –