2014-09-26 27 views
1

我有一個使用StreamTokenizer的簡單分詞器,它將數學表達式轉換爲各自的組件(如下)。我遇到的問題是,如果表達式中有一個名爲T_1的變量,它將分割爲[T,_,1],我想返回爲[T_1]。Java Tokenization:將任何由下劃線分隔的單詞當作一個單詞

我試圖用變量來檢查最後一個字符是否是下劃線,如果是這樣,將下劃線追加到list.Size-1上,但它看起來像一個非常笨重和低效的解決方案。有沒有辦法做到這一點?謝謝!

 StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(s)); 
     tokenizer.ordinaryChar('-'); // Don't parse minus as part of numbers. 
     tokenizer.ordinaryChar('/'); // Don't parse slash as part of numbers. 
     List<String> tokBuf = new ArrayList<String>(); 
     while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) //While not the end of file 
     { 
      switch (tokenizer.ttype) //Switch based on the type of token 
      { 
      case StreamTokenizer.TT_NUMBER: //Number 
       tokBuf.add(String.valueOf(tokenizer.nval)); 
       break; 
      case StreamTokenizer.TT_WORD: //Word 
       tokBuf.add(tokenizer.sval); 
       break; 
      case '_': 
       tokBuf.add(tokBuf.size()-1, tokenizer.sval); 
       break; 
      default: //Operator 
       tokBuf.add(String.valueOf((char) tokenizer.ttype)); 
      } 
     } 

     return tokBuf; 
+0

我沒有看到你所看到的。如果我傳入'T_1',我將它作爲輸出:'[null,T,1.0]' – 2014-09-26 18:26:41

+0

我覺得'wordChars'與答案有某種關係,但我不知道如何添加* word字符。似乎你只能設置一個範圍。令人驚訝的糟糕的Java文檔和API,IMO。在'StringTokenizer'上使用'StreamTokenizer'有沒有合理的理由? – 2014-09-26 18:31:28

+0

我真的很抱歉,我提供的代碼沒有完全修復。上面的代碼不應該包含'_'的情況。這是我試圖將它添加到列表中最後一個元素的遺蹟。不,沒有正當理由,我正在使用StreamTokenizer。你覺得StringTokenizer是優越的嗎? – Archetype90 2014-09-26 18:33:09

回答

3

這就是你想要的。

tokenizer.wordChars('_', '_'); 

這使_可識別爲單詞的一部分。

附錄:

此構建並運行:

public static void main(String args[]) throws Exception { 
    String s = "abc_xyz abc 123 1 + 1"; 
    StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(s)); 
    tokenizer.ordinaryChar('-'); // Don't parse minus as part of numbers. 
    tokenizer.ordinaryChar('/'); // Don't parse slash as part of numbers. 
    tokenizer.wordChars('_', '_'); // Don't parse slash as part of numbers. 


    List<String> tokBuf = new ArrayList<String>(); 
    while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) //While not the end of file 
    { 
     switch (tokenizer.ttype) //Switch based on the type of token 
     { 
     case StreamTokenizer.TT_NUMBER: //Number 
      tokBuf.add(String.valueOf(tokenizer.nval)); 
      break; 
     case StreamTokenizer.TT_WORD: //Word 
      tokBuf.add(tokenizer.sval); 
      break; 
     default: //Operator 
      tokBuf.add(String.valueOf((char) tokenizer.ttype)); 
     } 
    } 
    System.out.println(tokBuf); 
} 

run: 
[abc_xyz, abc, 123.0, 1.0, +, 1.0] 
+0

非常好!這實際上爲我做了。只需在tokenizer.ordinaryCharacter下面放置該行即可。 – Archetype90 2014-09-26 19:12:42

+0

對於其他人,我調整了這一點,以表明您可以多次調用'wordChars',它會考慮每個呼叫,而不僅僅是最近的呼叫。如何在javadoc中沒有記錄這是有點不尋常的。 – 2014-09-26 19:13:03

0

一個StringTokenizer可能是一個更好的選擇。如果是這樣,這裏是你如何使用它:

import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer;

public class Solution { 

    public static void main(String args[]) throws Exception { 
     StringTokenizer tokenizer = new StringTokenizer("T_1 1 * bar"); 
     List<String> tokBuf = new ArrayList<String>(); 
     while (tokenizer.hasMoreTokens()) //While not the end of file 
     { 
      tokBuf.add(tokenizer.nextToken()); 
     } 

     System.out.println(tokBuf); 
    } 
} 

此打印出來:

[T_1, 1, *, bar] 
相關問題