簡體   English   中英

掃描一個數字並返回輸入流中的詞素 - Java?

[英]Scanning a number and returning the lexeme in the input stream- Java?

我正在嘗試編寫一個方法來掃描輸入並返回一個字符串,該字符串表示在輸入字符串中找到的詞素。

到目前為止,這是我所擁有的,但我不知道我是否朝着正確的方向前進——所有幫助將不勝感激:)

private String scanNumbers(char input)
{
   String result= "";
   int value = in.read()
   if(value != -1)
   {
      If(isDigit(input))
       {
         result = Integer.toString(value);
        }
   }
 return result;
}

public static boolean isDigit(char input)
{
    return (input >= '0' && input <= '9');
}

謝謝我是解析/詞素/編譯器的新手。

介紹

似乎與家庭作業相關的問題在 SO 上的回答通常很慢 我們經常等到最后期限過去了!

您提到您是解析/詞素/編譯器主題的新手,並且需要一些幫助來編寫 Java 方法來掃描輸入並返回表示在輸入字符串中找到的詞素的字符串。 后來你澄清,表明你想要一個跳過字符直到找到數字的方法。

您的問題中有相當多的混淆,這會在您想要實現的目標上產生沖突。

不清楚您是否想學習在 Java 中執行詞法分析作為更大編譯器項目的一部分,您是否只想用數字來做,您是否正在尋找可以執行此操作的現有工具或方法或正在嘗試學習如何自己編程這些方法。 如果您正在編程,無論您只需要了解讀取數字,還是這只是您想要做的事情的一個例子。

詞法分析

詞法分析也稱為掃描,是閱讀由字符組成的文本語料庫的過程。 這可以用於多種目的,例如數據輸入、書面材料的語言分析(例如詞頻計數)或語言編譯或解釋的一部分。 當作為編譯的一部分完成時,它是一系列階段中的一個(通常是第一個),包括解析、語義分析、代碼生成、優化等。 在編寫編譯器時通常會使用代碼生成器工具,因此如果希望用 Java 編寫編譯器,那么通常會使用 Java 詞法生成器和 Java 解析器生成器來為這些編譯器組件創建 Java 代碼。 有時詞法分析器和解析器是手寫的,但對於新手來說,這不是推薦的任務。 需要編譯器編寫專家來手動構建編譯器而不是工具集。 有時,作為課堂練習,學生會被要求編寫代碼來執行一段詞法分析,以幫助他們理解這個過程,但這通常是針對一些詞素的,比如你的數字練習。

術語詞素用於描述組成由詞法分析器識別的單個實體的字符序列。 一旦被識別,它通常由一個token 表示 因此,作為詞法分析過程的一部分,詞素被標記替換。 詞法分析器有時會將詞素記錄在符號表中以供以后使用,然后再將其替換為標記。 這就是程序中的標識符通常在編譯器中記錄的方式。

有多種工具可用於在 Java 中構建詞法分析器。 兩個最常見的是JlexJFlex 為了說明它們是如何工作的,在跳過空格的同時識別整數,我們將使用以下規則

%%
WHITE_SPACE_CHAR=[\n\ \t\b\012]
DIGIT=[0-9]
%%
{WHITE_SPACE_CHAR}+  { }
{DIGIT}+   { return(new Yytoken(42,yytext(),yyline,yychar,yychar + yytext().length())); }
%%

它將由工具處理以生成 Java 方法來完成該任務。

用於描述詞素的符號通常寫成正則表達式 計算機科學理論可以幫助我們進行詞法分析器的編程。 正則表達式可以用 有限狀態自動機的形式表示。 有一種特殊的編碼風格可用於匹配有經驗的程序員在這種情況下會識別和使用的詞素,這涉及循環內的開關:

while ( ! eof ) {
  switch ( next_symbol() ) {

  case symbol:
      ...
  break;
  default:
        error(diagnostic); break;
  }
 }

一個簡單的詞法編程練習往往旨在向學生介紹這些概念。

Java 中的標記

拋開所有這些初步的解釋,讓我們深入了解您的 Java 代碼片段。 正如評論中提到的,Java 中從輸入流讀取字節和讀取字符之間存在差異,因為字符是 unicode,由兩個字節表示。 您在字符處理方法中使用了字節讀取。

識別輸入流中的簡單標記,特別是對於數據輸入,是一種常見的活動,以至於 Java 有一個特定的內置類,稱為 StreamTokenizer

我們可以通過以下方式執行您的任務,例如:

    // create a new tokenizer
     Reader r = new BufferedReader(new InputStreamReader( System.in ));
     StreamTokenizer st = new StreamTokenizer(r);

     // print the stream tokens
     boolean eof = false;
     do {

        int token = st.nextToken();
        switch (token) {
           case StreamTokenizer.TT_EOF:
              System.out.println("End of File encountered.");
              eof = true;
              break;
           case StreamTokenizer.TT_EOL:
              System.out.println("End of Line encountered.");
              break;
           case StreamTokenizer.TT_NUMBER:
              System.out.println("Number: " + st.nval);
              break;
           default:
              System.out.println((char) token + " encountered.");
              if (token == '!') {
                 eof = true;
              }
        }
     } while (!eof);

但是,這不會返回數字的詞素字符串,僅匹配數字並獲取值。

我看到您已經注意到Java 類 java.util.scanner因為您的問題將其作為標記。 這是另一個可以執行類似操作的類。 我們可以從輸入中得到一個整數詞素,如下所示:

Scanner s = new Scanner(System.in);
System.out.println(s.nextInt());

解決方案

最后,讓我們重新編寫原始代碼以查找跳過不需要的字符的整數的詞素,其中我使用java 正則表達式匹配

import java.io.IOException;    import java.io.InputStreamReader;
import java.util.regex.Pattern;
public class ReadNumbers {
    static InputStreamReader in = null;            // Have input source as a global
    static int value = -1;                         // and the current input value       
    public static void main ( String [] args ) {
        try {
            in = new InputStreamReader(System.in); // Set up the input
            value = in.read();                     // pre-fill the input state              
            System.out.println(scanNumbers()) ;               
        }
        catch (Exception e) {
           e.printStackTrace();            // print error
        } 
    }
    private static String scanNumbers() {
        String SkipCharacters = "\\s" ;           // Characters that can be skipped
        String result= "";                        // empty string to store lexeme
        int charcount=0;
        try {
            while ( (value != -1) && Pattern.matches(SkipCharacters,"" + (char)value) ) 
                // Now skip optional characters before the number
                value = in.read() ;               // pre-load the next character
            while ( (value != -1) && isDigit((char)value)) { 
               // Now find the number digits
               result = result + (char)value;    // append digit character to result
               value = in.read() ;               // pre-load the next character
            }
        } finally {
           return result;
        }
    }
    public static boolean isDigit(char input) {
        return (input >= '0' && input <= '9');
    }
}

后記

@markspace 的評論很有趣也很有用,因為它指出並非所有數字都是唯一的十進制數字。 考慮其他基數的數字,如十六進制。 Java 允許在不只使用數字0 .. 9那些數基中指定整數常量

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM