2016-09-30 41 views
1

我們需要製作一個詞法分析器,而且我的某個特定函數useLoad或更準確地說,遇到了一些麻煩,發生了什麼在使用useLoad之後的Main中。我看不出爲什麼我的掃描儀在java中拋出一個「NoSuchElementException」

我發現那是因爲...由於某種原因,buffer=keyboard.nextLine()正在拋出錯誤,因爲由於某種原因它沒有從鍵盤獲得更多輸入。我認爲.nextLine()應該強制它從用戶那裏獲得更多的輸入。我不知道爲什麼在這個特定方法之後拋出異常。它可以完成其他方法,並且不會失去閱讀能力。是否因爲我在另一個對象中有一個名爲鍵盤的變量並將其關閉?這似乎令人懷疑。試圖改變名字。沒有區別。

已使用但未在以下代碼中聲明的變量:關鍵字[0]是字符串「load」。 initial =傳入該函數的掃描器字符串。偏移量=一個計數器變量,用來查看我們讀過的行的距離。

useLoad函數(這是我認爲搞亂了),是在底部,但我包括它運行的所有內容(每個方法分開一個水平的規則),按時間順序,以防萬一我只是沒有看到發生了什麼。

public static void main(String[] args) { 
     Scanner keyboard = new Scanner(System.in); //the scanner for keyboard 
     int i = 0; 
     String buffer =""; 
     boolean loopControl == true; 
     SymbolTable mySym = new SymbolTable(); 

     System.out.println("READY FOR INPUT\n"); 

     while (loopControl == true){ 
      //read in the line 
      buffer = ""; 
      buffer = keyboard.nextLine(); 
      if(!mySym.checkStop(buffer)){ //if we didn't stop 
       mySym.primary(buffer); 
      } 
      else{//if we did stop 
       closeLoop(); 
      } 

      if (i >= 55){ 
       loopControl = false; 
       System.out.println(("You have gone over the limit ("+i+" lines) per execution. Please continue by running this program again.").toUpperCase()); 
       //just a safety precaution...you know... in case closeLoop doesn't work 
      } 
      i++; 
     } 


     keyboard.close(); 

    } 

if(initial.substring(0, Keywords[0].length()).equals(Keywords[0])){ //Load 
     //if this is working as expected, then we simply need to do what the keyword says to do. 
     offset += Keywords[0].length(); //we have moved this much deeper in to the line 
     useLoad(offset, initial); 
     offset = 0; //just make sure, once we are done with the line, we start back at the start of the next line. 
     return; //we found what we were looking for, get out. 
    } 

private void useLoad(int offsetIn, String readIn) { 
     double doubIn = 0; 
     //now get the value of the 
     Scanner keyboard = new Scanner(System.in); //the scanner for keyboard 
      System.out.println("\nENTER VALUE FOR " + readIn.toUpperCase()); 
      doubIn = keyboard.nextDouble();  
     keyboard.close(); 

     variables.create(readIn.substring(offsetIn), doubIn); 
    } 
+1

你在哪裏初始化'loopControl'? – beatrice

+1

'keyboard.close();'關閉鍵盤(duh),所以你不能輸入或讀取任何東西。 (其實這不是很正確,但足夠接近) – immibis

+0

@beatrice它是main類中的全局變量(所以其他方法可能會混淆它,比如closeLoop())。這就是爲什麼它沒有被複制。我忘了那個。我把它作爲局部變量加回來,因爲它沒有太大區別。 –

回答

0

我想我已經想通了你的問題。爲Java 7和8

Java文檔包括該行掃描儀的close方法文檔中:

如果此掃描器尚未關閉,並且其底層readable也實現Closeable接口,則該readable的close方法將被調用。

展望爲文檔系統,我發現System.in是InputStream類型你猜對了其中的,實現CloseableInputStream的方法文檔close表示它什麼都不做;然而,InputStreamabstractclose而不是標記爲final,這意味着它可以被覆蓋。 System.in會返回一個InputStream,這可能會 - 並且很明顯會 - - 做一些事情。

所以,問題是,你正在創建多個Scanner s的System.in,並且每次關閉他們中的任何一個,您關閉System.in,使之無用!

此問題實際上在另一個問題here中進行了討論,並給出瞭解決方案。這就是說,你的計劃,我建議以下兩種方法之一:

  • 第一種方法是有提及:要麼使用一個預先製作的包裝類或使自己的,它接受在其構造的InputStream。這個類'InputStream實現調用它的包裝對象的所有方法,除了close這是一個非賣品的方法,然後直接通過Wrapper(System.in)掃描儀,而不是System.in。但是,除非在特定的情況下,否則我會謹慎採取這種方法,因爲任何時候使用這些包裝中的一種,在其使用結束時需要記住它的包裝物體,除非它是System.in之類的東西。
  • 第二種方法:在程序中使用runner類,並在那裏初始化掃描儀。在施工期間將掃描儀送入所需物體,以供參考,然後允許他們完成所需的任務而不關閉類別內的掃描儀。一旦指定退出條件,返回到跑步者等級並從那裏返回close掃描儀。
+0

公平起見,@immibis實際上在我之前說過這一點,但由於您的輸入讀取器實際上命名爲'keyboard',所以沒有清楚地說明。他們試圖說我現在說的 - 調用一個'System.in'掃描器的'close'方法「關閉」鍵盤本身 – BHustus

+0

我想你可能是對的..我有類似的懷疑。處理我的Lisp程序讓我頭疼。我會盡力實施你早上說的話。 –

0

您關閉keyboard每次一輪循環。因此,你第二次從封閉的keyboard對象讀取。

快速瀏覽一下Scanner.nextLine文檔包含了新聞,這可能拋出:

NoSuchElementException - if no line was found 
+0

哎呀,對不起。那是從我使用ctrl + z 1的次數比我想象的少。我解決了這個問題,並且仍然遇到同樣的錯誤。 –

+0

您可能應該在調用nextLine之前調用hasNextLine。我對Scanner並不特別熟悉,但通常Java方法遵循haveNext/next模式。 hasNextLine的文檔說它可能會阻止輸入,對於nextLine它說沒有這樣的事情。 – dave

+0

hmm?我認爲nextLine和nextDouble從鍵盤讀入(或者是掃描器初始化)。我會嘗試的。行! –

相關問題