2012-07-30 4 views
2

간단한 문제가 있지만 요즘에는 큰 어려움을 겪고 있습니다. 화학 프로그램 (더 구체적으로 Android 앱)을 만들고 있는데 사용자가 입력 한 요소를 구분하는 메소드가 있습니다. 예를 들어 누군가 "FeZnKPb"를 입력해야하는 경우 "Fe", "Zn", "K"및 "Pb"로 분리됩니다.중첩 된 루프 - 배열 객체를 사용하여 문자열 요소 분리

이렇게하려면 몇 가지 중첩 루프와 변수를 사용하여 제어하고 있습니다. 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; 
     } 
    } 
} 

내 문제는 단지 예 : "철"또는 "아연"등이 문자 요소와 함께 작동한다는 것입니다. 나는 또한 "K"와 같은 다른 사람들을 인식하기를 원합니다. 다른 문제는 때때로 다른 일부 요소를 건너 뜁니다. 예를 들어 "FeZnHg"를 입력하면 "Fe", "Zn"및 "Hg"로 구분됩니다. 그러나 "ZnFeHg"와 같이 다른 순서로 입력하면 어떤 이유로 "Zn"과 "Hg"만 감지하지만 "Fe"는 감지하지 못합니다.

다른 방법으로 제대로 작동하려면 어떻게 해결할 수 있습니까?

+1

대소 문자 민감도는 제약 조건이 맞습니까? 즉, 머큐리는 항상 HG가 될 것입니까, 아니면 HG로 나타날 수 있습니까? –

+0

코드를 단계별로 디버깅 해 보셨습니까? 더 나은 정규 표현식을 사용하십시오. – Bhaskar

+0

@ NathanielFord 네, 항상 그렇게 될 것입니다. 나는 그것을 바로 잡을 다른 방법이있다. – Pkmmte

답변

5

요소는 항상 대문자와 하나 또는 두 개의 소문자 문자 (일부 매우 짧은 요소의 경우에만 2 개)를 감안할 때 일부 미리보기가있는 정규식을 사용하여 짧은 문자열에 입력하십시오.

문자열을 분할 방법과 일부 미리보기를 사용하여 요소 문자열로 분할 할 수 있습니다. 계정에 나다니엘 포드의 의견을 촬영 :

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, 납, 음을, K]

+1

문자열을 대문자로 구분하여이 솔루션과 동의합니다. 화학 요소를 열거 형에 넣고 비교 코드를 캡슐화하여 배열 인스턴스 멤버를 수정하는 대신 함수가 Set 를 반환하도록하는 것이 좋습니다. (그것은 당신이 정말로 원하는 것이 아닙니다). –

+0

@ NathanielFord 글쎄, 다른 값을 사용하기 때문에 다른 이유로 배열 인스턴스 멤버를 수정하고 싶습니다. 이 방법이 무효 인 이유 중 일부입니다. 메이슨이 제안한 것을 시도해보고 작동하는지 확인해 보겠습니다. – Pkmmte

+0

고마워, 메이슨! 당신의 솔루션은 조금 수정 한 후에 완벽하게 작동했습니다. – Pkmmte

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 문이 2 자만큼 잘못 진행됩니다. 예를 들어 Fe이 목록에서 Zn보다 앞에 오는 경우 Zn을 찾은 후 Fe을 찾지 않고 건너 뜁니다.
-2

여기 내 겸손한 제안이다 ... 당신의 프로그램의 미래를 위해서 나는 여러개의 원자가있을 때 같은 경우에 더 좋을 것이라고 생각한다. 어쨌든 그것이 필요하다면 ... 내가 무엇을 할 것인지. ..i는 소위 2 차원 행렬 (더 많은 메모리를 사용하지만 계산 능력은 더 낮습니다) 26x26 각 색인은 문자에 해당합니다 ... 그래서 우리는 원소 기호가 유일하고 2 문자 이하임을 압니다. 미안 : D) ...다음에 문자열을 하나씩 검사 할 것입니다. F와 e를 만날 수 있습니다. 이것은 자동으로 2 차원 행렬의 색인을 제안합니다. 그래서 색인을 보게 될 것입니다.) 그러면 일반 목록에 Fe를 추가 할 것입니다. 그러나 F 다음에 K를 보았습니다 ... 그러면 행렬을 보면 비어있는 것을 볼 수 있고 불소라고 결론 지을 것입니다 ... 어쨌든 나는 더 많은 메모리 공간을 덜 계산했다 ... 당신의 선택