我的字符串输入带有sin(b(x-c))+ d作为其格式。我应该使用什么分隔符表达式来分割它,以便我可以使用Integer.parse来获取a,b,c和d的数值?
所以,如果字符串输入是
sin 5x a=1, b=5, c=d=0
sin 5(x-4) a=1, b=5, c=4, d=0
2 sin 3(x-2) a=2, b=3, c=2, d=0
sin 5x + 3 a=1, b=5, c=0, d=3
4 sin 7(x+6) + 2 a=4, b=7, c=-6, d=2
11 sin 2x a=11, b=2, c=d=0
答案 0 :(得分:2)
PUH。每当您使用字符串提供抽象上下文(如数学函数)时,您应该考虑写:
TokenScanner,用于识别您的案例中的令牌:
功能名称'罪',
operator'(',')','+'
常数代币1,2,5。
从字符串中提取令牌后,您可以开始构建AST(抽象语法树)
通过评估此树,您可以执行计算。
看,如果你从上面提到的公式中得到了数字,你会采取哪些步骤呢?操作员,数字甚至功能名称本身可以在您的公式中的不同位置,否则您将对字符串本身进行非常复杂的分析。
构建令牌扫描仪很简单
构建AST似乎更复杂,但在这种情况下不是这样,因为表达式的语法不太复杂。
因此,不是根据你期望的那种表达方式分析整个字符串,而是集中于符号如何相互关联。例如。罪(3 +(2 + 4))。
给你一个形式的AST:
功能'sin'
操作员'('
const_value 3
操作员+
操作员'('
const_value 2
操作员'+'
const_value 4
operator')'
operator')'。
然后,您可以遍历该树以获取最内层的表达式,对其进行评估并重新生成它的结果。你知道每个函数 - 调用创建一个新的范围
以及每个开放的圆括号。
因此,不难发现,哪一个是最里面的。 TokenScanner基本上可以是以下形式:
读取字符串中的第一个字符,与令牌列表进行比较,当它匹配时,构建该令牌类型的对象,读取下一个令牌,构建该令牌的对象,将两者都链接起来令牌,例如通过第一个和下一个 - 指针等等。
要获得一个基本想法:
public class TokenScanner {
public TokenScanner() { }
public Token scan(String input) {
Token root = new Token();
Token prevToken = null;
for(int i = 0; i < input.length(),i++) {
Token newToken = null;
char c = input.getCharAt(i);
switch(c) {
case 's': //** s is the start of the word sin, and not used in other contexts in this example, so: **/
newToken = new FunctionToken();
break;
case '(':
newToken = new Expression();
case ')':
newToken = new Expression();
....
}
if(prevToken == null) {
root->next = newToken;
newToken->prev = root;
}
else {
newToken->prev = prevToken;
prevToken->next = newToken;
}
return root;
}
}
}
public class Token() {
public Token prev;
public Token next;
public int TOKEN_TYPE = 0;
public Token() {
}
}
public class FunctionToken extends Token {
static public int TOKEN_TYPE = 1;
}
public class Expression extends Token {
}
public class TokenTreeVisitor {
public void traverse(Token currentToken) {
switch(currentToken.TOKEN_TYPE) {
case 1:
enter((FunctionToken) currentToken);
}
}
}
虽然此处已有解释令牌,但您应该将token更改为OpenBracketToken和ClosingBracketToken for tokenScanner。但它显示了如何从令牌到表达式和你可以评估的表达式。
这又是一个检查表达式是否包含子表达式的过程。如果有任何,那么进程到该子表达式。如果不是,则评估子表达式并将该表达式替换为该树中的表达式
例如
原始子表达式(5 +(1 + 7))
表达式exp仅包含const_value(1),运算符'+',const_value(7)
通过Int.parse(1)+ INt.parse(7),
class ExpressionResult extends Expression {
public int result;
}
result = new ExpressionResult(); result->result = 8;
exp->prev->next = result; result->prev = exp->prev; result->next = exp->next;
再次扫描并替换递归
exp2现在是const_value(5)+ operator'+'+ expression_result(8)
所以你可以Int.parse(5)+ exp2-&gt; next-&gt;结果;
等等。安静琐事,不是吗? ;)
答案 1 :(得分:1)
我认为你需要一个小的解析器。我认为你不能
只用regexp来做,但我没有试图严格证明这一点。
试试这个代码。我没有在你的所有输入上测试它但是它
应该给你一个想法。
public class Test002 {
// private static String s = " 10 sin 5 ( x - 4 ) - 14 ";
// private static String s = " 10 sin 2x ";
private static String s = " -4 sin -7 (x+6) - 2 ";
private static int i = 0;
public static void main(String[] args){
String str = s.replaceAll(" ", "");
s = str;
parseExpr();
}
private static void parseExpr(){
parseA();
parseSin();
parseSinArgument();
parseD();
}
private static void parseSinArgument(){
parseB();
if (s.charAt(i) == '('){
parseOpenBracket();
parseX();
parseC();
parseCloseBracket();
}else{
parseX();
}
}
private static void parseA(){
int j = i;
while (s.charAt(i) != 's') i++;
System.out.println("A=[" + getToken(j, i) + "]");
// stay at the 's' now!
}
private static void parseSin(){
int j = i;
while (s.charAt(i) != 'n') i++;
i++;
// move past the 'n' now!
}
private static void parseB(){
int j = i;
while ( s.charAt(i) == '-' || Character.isDigit( s.charAt(i) )) i++;
System.out.println("B=[" + getToken(j, i) + "]");
}
private static void parseOpenBracket(){
int j = i;
i++;
System.out.println("OPEN_BRACKET=[" + getToken(j, i) + "]");
}
private static void parseX(){
int j = i;
while (s.charAt(i) != 'x') i++;
i++;
System.out.println("X=[" + getToken(j, i) + "]");
}
private static void parseC(){
int j = i;
while (s.charAt(i) != ')') i++;
System.out.println("C=[" + getToken(j, i) + "]");
}
private static void parseCloseBracket(){
int j = i;
i++;
System.out.println("CLOSE_BRACKET=[" + getToken(j, i) + "]");
}
private static void parseD(){
int j = i;
while (i<s.length()) i++;
System.out.println("D=[" + getToken(j, i) + "]");
}
private static String getToken(int i1, int i2){
String str = s.substring(i1, i2);
str = str.replaceAll(" ", "");
return str.trim();
}
}