2012-07-30 103 views
2

我有一个简单的问题,但最近它一直在推动着我的坚果。 我正在制作化学程序(Android应用程序,更具体),我有一种方法可以分离用户输入的元素。例如,如果有人输入“FeZnKPb”,它将被分成“Fe”,“Zn”,“K”和“Pb”。嵌套For-Loops - 使用数组对象分隔字符串元素

为此,我使用了几个嵌套循环和变量来控制它。我拥有Chem []数组中定义的所有元素。然后将分隔的元素存储在名为savedChem []的数组中。它基本上只是遍历所有元素常量(Chem []),并将这些元素的名称和公式复制到savedChem []中,如果它与输入匹配的话。

这里是我的代码如下:

public void separateElements(String Input) 
{ 
    boolean found = false; 
    int start = 0; 
    int end = 2; 
    int length = Input.length(); 

    while(length >= end) 
    { 
     for(int x = 0; x < numChemicals; x++) 
     { 
      if((end + 0) > length) 
      { 
       end += 5; 
       break; 
      } 
      if(Input.substring(start, end).equals(Chem[x].getFormula())) 
      { 
       savedChem[numSaved].setName(Chem[x].getName()); 
       savedChem[numSaved].setFormula(Chem[x].getFormula()); 
       numSaved++; 
       start += 2; 
       end += 2; 
       found = true; 
      } 
      else 
      { 
       found = false; 
      } 
     } 
     if(!found) 
     { 
      start += 2; 
      end += 2; 
     } 
    } 
} 

我的问题是,它只有2个字符的元素,如“铁”或“锌”的作品。我希望它也能识别像“K”的其他人。另一个问题是,它有时会跳过一些其他元素。例如,如果我输入“FeZnHg”,它会将它们分离为“Fe”,“Zn”和“Hg”。但是,如果我按照“ZnFeHg”这样的不同顺序输入它们,则由于某种原因,它只能检测到“Zn”和“Hg”,而不是“Fe”。

还有什么其他方法可以解决这个问题,使其正常工作?

+1

是否正确的大小写敏感性约束?也就是说,水星会一直汞,或者它可能会显示为HG? – 2012-07-30 22:37:25

+0

您是否尝试过一步一步地调试代码?还是用一个正则表达式。 – Bhaskar 2012-07-30 22:46:23

+0

@NathanielFord是的,它永远是这样的。我有另一种方法来纠正这种情况。 – Pkmmte 2012-07-30 22:58:13

回答

5

鉴于元素总是或者是大写字母和一个或两个小写字母(而且两个只在一些非常短的元素的情况下),你可以使用正则表达式来分割你的输入到短字符串中。

您可以使用split方法和一些lookahead将字符串拆分为元素字符串。以纳撒尼尔·福特的评论到:

public enum ChemicalElement { 
    F, Fe, Zn, K, Pb, Umm, //and so on... 
} 

public List<ChemicalElement> separateElements(String input) { 
    String[] inputParts = input.split("(?=[A-Z]{1,1}[a-z]{0,2})"); 

    List<ChemicalElement> elementList = new LinkedList<ChemicalElement>(); 
    for (int i = 1; i < inputParts.length; i++) { 
     String inputPart = inputParts[i]; 

     // note: throws IllegalArgumentException for unknown elements 
     ChemicalElement element = ChemicalElement.valueOf(inputPart); 
     if (null != element) { 
      elementList.add(element); 
     } 

    } 
    return elementList; 
} 

所以测试输入这样的:

String input = "FeZnKPbUmmK"; 
List<ChemicalElement> elements = this.separateElements(input); 

会给你下面的列表:

[铁,锌,钾,铅,嗯, K]

+1

我同意这种解决方案,假设字符串是大写字母分隔的。我可能还建议将化学元素放入一个枚举中,并在其中封装比较代码,以便您的函数可以返回一个'Set '而不是修改一个数组实例成员。 (这不是你想要的)。 – 2012-07-30 22:58:02

+0

@NathanielFord嗯,我真的希望它修改一个数组实例成员出于其他原因,因为我也会使用它的其他值。这是该方法无效的原因之一。 我会尝试梅森建议的,看看它是否有效。 – Pkmmte 2012-07-30 23:30:10

+0

谢谢,梅森!稍加修改后,您的解决方案就可以完美运行。 – Pkmmte 2012-07-31 00:40:53

0
  1. 而不是预先定义结束,使结束start + length of chemical name being tested。所以你会比较Chem[x].getFormula().equals(Input.substring(start, start + Chem[x].getFormula().length()))另外,你会提前startChem[x].getFormula().length()。我认为你还需要验证start + Chem[x].getFormula().length()小于总长度,否则你会得到String Index越界异常。
  2. 当您发现化学名称匹配时,您需要从内部循环break检查化学名称,否则您会继续与以后的名称进行比较,并可能以found=false结束。所以你的底部if声明错误地前进了两个字符。例如,如果Fe在您的列表中出现在Zn之前,它在找到Zn后将不会找到Fe,并且会跳过它。
-2

这里是我卑微的暗示......对于你的程序的未来,我想它会在诸如当你有多个O原子的情况下更好......如果这是需要的话......我会做什么。 ..我会创建一个所谓的二维矩阵(使用更多的内存,但计算能力较低)26x26,其中每个索引对应一个字母......所以我们知道,元素符号是唯一的,最多2个字母(我不知道那些实验的...遗憾:d)...那么你会逐一扫描字符串...可以说你遇到F和E ..这会自动建议2d矩阵的索引...所以你会看看那个索引里面...如果它是满的(通过某些符号),那么你会将Fe添加到你的一般列表中......但是让我们在F后看到一个K ......然后当你看到矩阵时,你会看到它是空的,你会得出它是氟的结论......无论如何,我说更多的内存空间更少的计算......你的选择

相关问题