代码:
public static void main(String[] args) {
Arrays.asList("a+(b*c)-2-a", "(a+b*(2-c)-2+a)*2", "(a*b-(2+c)", "2*(3-a))", ")3+b*(2-c)(")
.stream().forEach((expression) -> {
if (replaceAll(expression, "[(]") == replaceAll(expression, "[)]")) {
System.out.println("correct");
} else {
System.out.println("incorrect");
}
});
}
private static int replaceAll(String word, String regex) {
int count = word.length() - word.replaceAll(regex, "").length();
return count;
}
我必须检查表达式是否有效。确定表达式是否有效的是括号。如果它是自闭的,则有效,否则不是。
我的代码几乎正确,正在打印:
correct
correct
incorrect
incorrect
correct
但它必须打印
correct
correct
incorrect
incorrect
incorrect -> the last expression isn't valid.
答案 0 :(得分:4)
您不仅需要检查开括号的数量是否与已关闭的数量相匹配,而且还需要检查每个右括号是否在打开一个不关闭"关闭"然而:
static boolean checkParentheses(String s) {
int opened = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(')
opened++;
else if (s.charAt(i) == ')') {
if (opened == 0) // means that all parentheses are "closed" yet
return false;
opened--;
}
}
return opened == 0;
}
如果您严格需要参与正则表达式,请执行以下操作:
static boolean checkParentheses(String s) {
// capture a text starting with one opening parenthesis,
// ending with one closing and having no parentheses inside
Pattern p = Pattern.compile("\\([^()]*\\)");
Matcher m;
while ((m = p.matcher(s)).find())
s = m.replaceAll("");
return !(s.contains("(") || s.contains(")"));
}
答案 1 :(得分:1)
你的问题是只计算括号是不够的;你还需要找到一个&#39;)&#39;太早了。例如&#34;)(&#34;即使有相同数量的开括号和右括号也无效。
一种方法是保持计数。从零开始。每当您看到&#39;(&#39;,count++
。每次看到&#39;)&#39;,count--
。
减量后,if(count<0)
输入无效。
在输入结束时,if(count!0)
输入无效。
有人指出,这不能在一个正则表达式中完成。这是因为正则表达式代表有限状态机。 count
原则上可以无限增加。
如果选择最大嵌套深度,可以编写正则表达式进行检查。例如,最大深度为3:
x*(<x*(<x*(<x*>)*x*>)*x*>)*x*
(我已经使用&#39; x&#39;而不是任意字符,为了便于阅读。将其替换为[^<>]
以实际匹配其他字符。我还使用了{{为了便于阅读,再次使用{}}}而不是<>
。此处的\(\)
用于分组。)。
你可以通过用()
替换中间的x*
来让它更深入地工作 - 但是你永远不能制作一个不会在某个深度停止工作的正则表达式
另一种方法更接近真正的语句解析器对嵌套结构的处理方式:recurse。像(伪代码)的东西:
x*(<x*>)*x*
此处def consumeBlock() {
switch(next char)
case end-of-input
throw error -- reached end of input inside some parentheses
case '('
consumeBlock() -- go down a nesting level
break;
case ')'
return -- go up a nesting level
default
It's an uninteresting character. Do nothing.
(a real parser compiler would do something more interesting)
}
假设您刚刚消费了一个&#39;(&#39;并且您打算在其配对之前阅读。
您的一些输入不是以&#39;(&#39;开头,首先附加&#39;以及#39;到最后,作为一对&#34;沉默&#34; &#39;)&#39;你说它已经被消耗了。
伪代码已经显示,如果你点击输入结束的中间块,它的输入无效。此外,如果您在consumeBlock()
的顶级电话回复时没有输入结束,则输入无效。
答案 2 :(得分:0)
您可以通过char查询char并使用计数器告诉语句中的括号级别。
boolean valid = true;
int level = 0;
for(int i=0; i < expr.length(); i++) {
if(expr.charAt(i) == '(') level++;
if(expr.charAt(i) == ')') level--;
if(level < 0) { // ) with no (
valid = false;
break;
}
}
if(level > 0) valid = false; // ( with no )
return valid; // true if level returned to 0