求高手帮忙写个算法
首先祝大家过年好。
我的问题是这样:
有一种字符串表示的查询条件,如:name=wang,这是单一条件的,如果有多个条件以"与"或者"或"的关系出现,则表示方法是这样:&(name=wang)(age=20),或者:|(name=wang)(name=li)(name=zhao),大家可以看出,就是将"与"或者"或"的符号写在最前面,而将每个条件用圆括号括起来挨个写在后面。当然,大家知道,单纯的"与"、"或"关系有时候不能解决复杂的逻辑,所以"&"、"|"有可能嵌套出现多次,如这种写法:&(|(name=wang)(name=li))(age=20),这就表示"name=wang或者name=li、并且age=20".
然而QA总是能找到问题,我们是用圆括号表示一个条件的,但是如果条件信息里本身就有"("或")"怎么办,如&(name=(wang)(age=20),对于这样的信息,第二个"("应该是属于有用的条件信息,就是name=(wang,试了一下,对于这样的信息,我们以前的代码确实出现处理错误,所以现在需要的是将应该属于正常查询条件信息的"("或")"进行一个转义,转义方法是这样:如果这个需要转的字符是"(",则需要转为:Integer.toHexString('('),")"也以同样的方法。这样我们的代码就不会将其当做边界符"("或")"处理。
现在的问题就是怎样判断一个"("或")"是有用的条件信息还是表示边界的符号。求达人们给段代码,最好写成方法,传入原始输入的条件字符串,返回转换后的字符串。
如&(name=wang))(age=20)应该会变成&(name=wang\29)(age=20)输出,如果最外层有多余的成对的"()"则可以直接去掉,如只有一个条件的还加了括号((name=wang)),这样的多层括号其实已经是多余的,只要是成对的,就不用处理,可以直接返回,也可以返回(name=wang)或name=wang,但是有落单的"("或")"就必须转义。
[解决办法]
(name=(wang)怎么说?
[解决办法]
(name=(wang))怎么说?
[解决办法]
不知道这样可符合?
for example
import java.util.*;public class csdn { public static void main(String[] args) throws Throwable { String testData[] = {"&((name=wang))(age=20)", "&((name=wang)(age=20)", "&(name=wang))(age=20)", "&(name=wang)))((age=20)", "&(((name=wang))((age=20))))"}; for (String str : testData) { //测试数据 convert(str); } } public static String convert(String str) { Stack<String> st = new Stack<String>(); List<String> ls = new ArrayList<String>(); StringBuilder sb = new StringBuilder(); boolean match = false; for (int i=0; i<str.length(); i++) { //先转换多余的")" String s = str.substring(i, i+1); if (s.equals(")")) { sb.delete(0, sb.length()); match = false; while (st.size() > 0) { String ss = st.pop(); if (ss.equals("(")) { if (sb.length() == 0 || (sb.charAt(0) == '(' && sb.charAt(sb.length()-1) == ')')) { st.push(sb.toString()); } else { sb.insert(0, ss); sb.append(s); st.push(sb.toString()); } match = true; break; } else { sb.insert(0, ss); } } if (!match) { if (sb.charAt(sb.length()-1) == ')') { sb.deleteCharAt(sb.length()-1); sb.append(String.format("\\%x", (int)(')'))); sb.append(s); } else { sb.append(String.format("\\%x", (int)(')'))); } st.push(sb.toString()); } } else { st.push(s); } } while (st.size() > 0) { //再转换多余的"(" String s = st.pop(); if (s.equals("(")) { if (ls.size() > 0) { String ss = ls.remove(0); if (ss.startsWith("(") && ss.endsWith(")")) { ls.add(0, String.format("%s\\%x%s", s, (int)('('), ss.substring(1))); } else { ls.add(0, String.format("\\%x", (int)('('))); } } else { ls.add(String.format("\\%x", (int)('('))); } } else { ls.add(0, s); } } sb.delete(0, sb.length()); for (String s : ls) { //获得最后结果 sb.append(s); } System.out.println(sb); return sb.toString(); }}
[解决办法]
发现上面有失误,修改了一下
import java.util.*;public class csdn { public static void main(String[] args) throws Throwable { String testData[] = {"&((name=wang))(age=20)", "&(name=(wang)(age=20)", //here "&(name=wang))(age=20)", "&(name=wang)))((age=20)", "&(((name=wang))((age=20))))", "&(|(name=wang)(name=li))(age=(20)"}; for (String str : testData) { convert(str); } } public static String convert(String str) { Stack<String> st = new Stack<String>(); List<String> ls = new ArrayList<String>(); StringBuilder sb = new StringBuilder(); boolean match = false; for (int i=0; i<str.length(); i++) { String s = str.substring(i, i+1); if (s.equals(")")) { sb.delete(0, sb.length()); match = false; while (st.size() > 0) { String ss = st.pop(); if (ss.equals("(")) { if (sb.length() == 0 || (sb.charAt(0) == '(' && sb.charAt(sb.length()-1) == ')')) { st.push(sb.toString()); } else { sb.insert(0, ss); sb.append(s); st.push(sb.toString()); } match = true; break; } else { sb.insert(0, ss); } } if (!match) { if (sb.charAt(sb.length()-1) == ')') { sb.deleteCharAt(sb.length()-1); sb.append(String.format("\\%x", (int)(')'))); sb.append(s); } else { sb.append(String.format("\\%x", (int)(')'))); } st.push(sb.toString()); } } else { st.push(s); } } sb.delete(0, sb.length()); while (st.size() > 0) { String s = st.pop(); if (s.equals("(")) { if (sb.length() > 0) { int idx = sb.indexOf("("); if (idx >= 0) { sb.replace(idx, idx+1, String.format("\\%x", (int)('('))); sb.insert(0, s); } else { sb.insert(0, String.format("\\%x", (int)('('))); } } else { sb.append(String.format("\\%x", (int)('('))); } ls.add(0, sb.toString()); sb.delete(0, sb.length()); } else { sb.insert(0, s); } } if (sb.length() > 0) { ls.add(0, sb.toString()); } sb.delete(0, sb.length()); for (String s : ls) { sb.append(s); } System.out.println(sb); return sb.toString(); }}
[解决办法]
类似于中值遍历,搞个调用栈呗
[解决办法]
&(|(name=wang)(name=li))(age=20)
大哥你是不是少些了个括号啊按照你说的逻辑判断应该是这样的把
&(|(name=wang)(name=li)))(age=20)
[解决办法]
协议或者文件格式或者dsl的设计一定要考虑到所有特殊情况,特别是转义,(有经验的话考虑这些花不了你几分钟),一个合格的程序员在开始设计前就应该考虑清楚这些问题,而不是在实现出来之后修修补补,那样太晚了。
自己缺少经验就多向成熟产品学习借鉴。SQL用过吧?SQL是怎么解决这个问题的?字符串用引号包围起来就可以了啊。而且还支持field1=field2这种写法。比自己造个奇丑无比的新语法强多了。
试着把自己的语法形式化出来,然后语法里有没有漏洞就一目了然。
[解决办法]