嵌套对象解析器的字符串

时间:2019-01-20 19:27:45

标签: java

我正在编写一个图形界面程序来解决化学方程式,并将其用作其他功能,例如在不同的窗口中显示周期表。

正如标题所示,对象解析器的字符串有问题,希望对它的使用有所帮助。

它得到一个String公式(C6H14 + O2 => CO2 + H2O)并将其划分为不同的对象(分子具有存储名称和数量的元素列表),然后返回。注意*我将其设置为void仅出于测试目的。

我将功能分为两部分:第一部分将String读入Element对象;名称和数量。第二部分制作分子对象,并检查一个分子在哪里开始,另一分子在何处结束并相应地放置元素对象。这就是为什么我不过滤掉+=>等数字动作的原因。

解析器:

    public void formatFormula(String formula) {
    List[] temp = new List[] {
        new ArrayList<Molecule>(),
        new ArrayList<Molecule>()
    };
    List<Element> ell = new ArrayList<>();
    boolean newMol = true;
    String crnN = null;
    int crnQ=0;
    int side = 0;
    for (int i=0;i<formula.length()+1;i++) {
        String d;
        try { d = formula.substring(i,i+1); } catch (Exception e) { d = formula.substring(i-1); }
        if (Character.isWhitespace(d.charAt(0))) continue;

        if (isNumber(d)) {
            crnQ = Integer.parseInt(crnQ+d);
        } else if (d == d.toUpperCase()) {
            if (crnN != null)
                ell.add(new Element(crnN,crnQ));
            crnN = d;
            crnQ = 0;
        } else {
            crnN = crnN + d;
        }
    }
    Element e;
    for (int i=0;i<ell.size();i++) {
        e = ell.get(i);
        if (e.getName().charAt(0) == "+".charAt(0)) {
            newMol = true;
            continue;
        }
        if (e.getName().charAt(0) == "=".charAt(0) || e.getName().charAt(0) == ">".charAt(0)) {
            newMol = true;
            side = 1;
            continue;
        }

        if (newMol) {
            temp[side].add(new Molecule());
            newMol=false;
        } else {
            ((Molecule)temp[side].get(temp[side].size()-1)).addElement(e);
        }
    }
    // Debugging.
    for (Object f:temp[1]) {
        System.out.println(((Molecule) f).getElements().get(0).getName());

    }
}

我从中得到的价值观是完全错误的。在2侧的第二个列表为空,在1侧的列表22具有相同的值,并且Molecule对象的元素都不超过一个。

它应该返回一个二维的分子数组,一个在箭头前,另一个在后。这些分子对象存储Element对象。

输入: C6H14 + O2 => CO2 + H2O 输出:

    C6H14         +     O2              =>     CO2            +     H2O
Obj(Molecule){    | Obj(Molecule){      || Obj(Molecule){     | Obj(Molecule){
Obj(Element){C:6} | Obj(Element){O:2}}  || Obj(Element){C:1}  | Obj(Element){H:2}
Obj(Element){H:14}}                     || Obj(Element){O:2}} | Obj(Element){O:1}}

注意*,这只是对象的表示。但是Molecule存储了Element的列表,这些列表又存储了Stringint的值。

2 个答案:

答案 0 :(得分:0)

很奇怪的代码。

我建议很少重构

1)使用“ =>”字符串拆分公式,并获得两个可以分别解析的公式(左和右)。

String delim="=>";
int p=s.indexOf(delim); 
String left=s.substring(0, p); 
String right=s.substring(p+delim.length());
List<Molecule> leftMolecules=parse(left);
List<Molecule> rightMolecules=parse(right);

2)创建函数parse来解析您的公式的令牌

List<Molecule> parse(String formula) {
  String [] molecules = formula.split("\\+"); // + is special character and requires escaping
  List<Molecule> result = new ArrayList<>();
  for (String m : molecules) {
     m = m.trim(); // remove leading and trailing spaces
     // here you parse single molecule like H2O etc
     ...
  }
  return result;
}

答案 1 :(得分:0)

我通过使用一个临时的Molecule对象变量解决了这个问题,然后将其插入列表中。

public Molecule[][] ParseString(String formula) {
List[] temp = new List[] {
    new ArrayList<Molecule>(),
    new ArrayList<Molecule>()
};
List<Element> ell = new ArrayList<>();
String crnN = null;
int crnQ=0;
int side = 0;
for (int i=0;i<formula.length()+1;i++) {
    String d;
    try { d = formula.substring(i,i+1); } catch (Exception e) { d = formula.substring(i-1); }
    if (Character.isWhitespace(d.charAt(0))) continue;

    if (isNumber(d)) {
        crnQ = Integer.parseInt(crnQ+d);
    } else if (d == d.toUpperCase()) {
        if (crnN != null)
            ell.add(new Element(crnN,crnQ));
        crnN = d;
        crnQ = 0;
    } else {
        crnN = crnN + d;
    }
}

Molecule tempM = new Molecule();
boolean newMol = false;
for (Element e:ell) {
    String n = e.getName();

    if (n.charAt(0) == "+".charAt(0)) {
        newMol = true;
        temp[side].add(tempM);
        tempM = new Molecule();
    }
    if (n.charAt(0) == "=".charAt(0)) {
        newMol = true;
        if (side == 0)
            temp[side].add(tempM);
        side = 1;
        tempM = new Molecule();
    }
    if (n.charAt(0) == ">".charAt(0)) {
        side = 1;
        tempM = new Molecule();
        continue;
    }
    if (newMol) {
        newMol = false;
    } else {
        tempM.addElement(e);
    }
}
temp[1].add(tempM);

return new Molecule[][]{
        ((Molecule[]) temp[0].toArray(new Molecule[temp[0].size()])),
        ((Molecule[]) temp[1].toArray(new Molecule[temp[1].size()]))
};