2013-05-11 51 views
3

我想標記由整數,浮點數,運算符,函數,變量和括號組成的字符串。下面的例子應該點亮的問題本質:用於複雜數學表達式的高級標記器

當前狀態:

String infix = 4*x+5.2024*(Log(x,y)^z)-300.12 

期望狀態:

String tokBuf[0]=4 
String tokBuf[1]=* 
String tokBuf[2]=x 
String tokBuf[3]=+ 
String tokBuf[4]=5.2024 
String tokBuf[5]=* 
String tokBuf[6]=( 
String tokBuf[7]=Log 
String tokBuf[8]=( 
String tokBuf[9]=x 
String tokBuf[10]=, 
String tokBuf[11]=y 
String tokBuf[12]=) 
String tokBuf[13]=^ 
String tokBuf[14]=z 
String tokBuf[15]=) 
String tokBuf[16]=- 
String tokBuf[17]=300.12 

所有的技巧和方法,將不勝感激。

+2

使用類似[ANTLR(http://www.antlr.org/)來定義喲語法你的表達併爲它生成一個解析器。 – 2013-05-11 15:23:23

+0

yacc是另一個好工具。很可能你想要一個符號圖而不是數組。 – 2013-05-11 15:28:31

+0

如果您正在構建表達式評估器,請在嘗試之前使用GNU libmatheval或muParse :) – 2013-05-11 15:30:14

回答

5

使用Java流標記器。該接口是一個有點古怪,但人會使用它:

http://docs.oracle.com/javase/7/docs/api/java/io/StreamTokenizer.html

示例代碼解析的請求字符串列表(你可能想直接使用標記生成器或至少使用一個對象列表,以便店面數量直接作爲雙人間):

public static List<String> tokenize(String s) throws IOException { 
    StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(s)); 
    tokenizer.ordinaryChar('-'); // Don't parse minus as part of numbers. 
    tokenizer.ordinaryChar('/'); // Don't treat slash as a comment start. 
    List<String> tokBuf = new ArrayList<String>(); 
    while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) { 
    switch(tokenizer.ttype) { 
     case StreamTokenizer.TT_NUMBER: 
     tokBuf.add(String.valueOf(tokenizer.nval)); 
     break; 
     case StreamTokenizer.TT_WORD: 
     tokBuf.add(tokenizer.sval); 
     break; 
     default: // operator 
     tokBuf.add(String.valueOf((char) tokenizer.ttype)); 
    } 
    } 
    return tokBuf; 
} 

試運行:

System.out.println(tokenize("4*x+5.2024*(Log(x,y)^z)-300.12")); 
[4.0, *, x, +, 5.2024, *, (, Log, (, x, ,, y,), ^, z,), -, 300.12] 
+0

p.s.你可能會對我在github上的表達式解析器感興趣:https://github.com/stefanhaustein/expressionparser – 2016-10-11 16:29:55

+0

你會想添加tokenizer.ordinaryChar('/'),因爲'/'被視爲EOF,並且循環將過早終止如果有斜線操作符。 – 2018-01-21 14:07:19

+0

完成。識別C++評論是否能夠解決這個問題?可能最安全的是使用reset(),然後明確地設置所有內容...... – 2018-01-23 10:42:18

1

http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form
http://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools
算法的實施例:
步驟#1:讀 '4'=>數字標記=>讀取字符,直到達到非NUM符號(即 '*')。首先剛剛閱讀,tokBuf [0]是一個數字標記。
步驟#2:讀取'*'=>令牌表示二元運算符。
步驟#3:讀取'x'。也許,一個函數符號=>將下一個標記標記爲var-token。
依此類推。
下一步是評估,我猜?反向波蘭語法或語法樹將有所幫助...