2011-10-15 4 views
2

자바 문자열 비교에 사소한 문제가 있습니다.이상한 자바 문자열 비교

String을 받아서 사용자 정의 트리 형식으로 구문 분석하는 클래스를 작성했습니다. 나는이 트리를 String으로 다시 변환하는 toString 클래스를 작성했다. 유닛 테스트의 일부로, 나는 toString 메소드에 의해 생성 된 String이 처음에 파싱 된 String과 동일한 지 확인하고있다.

다음은 몇 가지 출력물을 사용한 간단한 테스트로, 어떻게 진행되는지 확인할 수 있습니다.

final String exp1 = "(a|b)"; 
final String exp2 = "((a|b)|c)"; 
final Node tree1 = Reader.parseExpression2(exp1); 
final Node tree2 = Reader.parseExpression2(exp2); 
final String t1 = tree1.toString(); 
final String t2 = tree2.toString(); 

System.out.println(":" + exp1 + ":" + t1 + ":"); 
System.out.println(":" + exp2 + ":" + t2 + ":"); 

System.out.println(exp1.compareToIgnoreCase(t1)); 
System.out.println(exp2.compareToIgnoreCase(t2)); 

System.out.println(exp1.equals(t1)); 
System.out.println(exp2.equals(t2)); 

다음과 같은 결과가 출력됩니다. (NB ":"- 나는 프로그래머에게 여분의 공백이 없도록 할 수 있도록 내보낼 때에는로 사용)을

:(a|b):(a|b): 
:((a|b)|c):((a|b)|c): 
-1 
-1 
false 
false 

수동으로 각각 그들이 정확히 동일 T1과 T2에 EXP1 및 EXP2 문자열을 비교하는 기준으로합니다. 그러나 어떤 이유로 자바는 주장하고있다.

.equals() 대신 ==을 사용하는 것이 분명한 실수는 아니지만 두 개의 겉으로는 동일한 문자열이 다른 이유는 무엇입니까? 어떤 도움을 많이 주시면 감사하겠습니다 :)

+0

diff 도구와 비교해 보면 다른 문자가 표시됩니다. 아니면 "수동으로 비교"한다는 의미입니까? –

+2

도움을 받으려면 구문 분석 및 toString 코드가 필요합니다. –

+0

@DonRoby 확실히 문제는 어떻게 생성되는지보다는 오히려 동일하게 보이는 두 개의 문자열을 비교하는 것입니다. 솔루션을 더 빨리 찾을 수 있도록 코드를 게시 해 드리겠습니다.하지만 지금은 조금 혼란 스럽습니다. –

답변

3

문자열 중 하나에 null 문자가 있습니까? System.out.println(...)을 사용하면이 아이콘이 표시되지 않을 수 있습니다.

예를 들어,이 클래스를 고려 : 나는 리눅스에서이 작업을 실행하면

public class StringComparison { 
    public static void main(String[] args) { 
     String s = "a|b"; 
     String t = "a|b\0"; 
     System.out.println(":" + s + ":" + t + ":"); 
     System.out.println(s.equals(t)); 
    } 
} 

는 나에게 다음과 같은 출력을했다 :

 
:a|b:a|b: 
false 

(나는 또한 Windows에서 그것을 실행하지만, 널 문자 공간으로 나타났다.)

+0

이것이 원인 인 것 같습니다. null 문자에 대해서는 알고 있지만 검사는 생각하지 않았습니다. 나는 exp1 (5)의 길이와 t1 (6)의 길이를 얻는다. 그래서 나는 결국 null 문자를 어떻게 든 추가한다고 가정한다. 감사 :) –

2

글쎄, 그것은 확실히 보이는 괜찮아. 두 문자열을 반복하여 charAt을 사용하여 모든 단일 문자를 다른 문자열의 동등 문자열과 비교하는 것이 좋습니다. 이것은 최소한, 문제가되는 성격을 당신에게 말할 것입니다.

길이와 같은 두 문자열에 대한 다른 정보도 모두 출력합니다.

그것은 같은를 보면서 문자 중 하나는, 당신은 또한 출력을 캡처 할 수 있습니다

:-) 다른 유니 코드 도플 갱어가 될 수있을와 같은 그것에 대한 자세한 바이너리 덤프를 할 수 gvim으로로드하고 16 진 변환 도구를 사용하거나 캡처 된 출력에서 ​​od -xcb (사용 가능한 경우)을 실행합니다. 이진 검사 수준에 도달 할 때 명백한 차이가있을 수 있습니다.

+0

나는 그 생각도했지만 문자열을 반복하는 간단한 루프를 썼다, 그리고 그것은 각각의 개별 문자가 동일하다고 말한다. –

1

나는 몇 가지 제안을

  • 복사 각 출력 메모장에 붙여 넣기 (또는 유사한 편집기), 다음 다시 복사하고이

    에서 System.out.println ("(A | B)"같은 않습니다. compareToIgnoreCase를 ("(A | b) "));

  • 각 문자의 정수 표현을 인쇄하십시오.이상한 유니 코드라면, int 표현은 다를 것이다.

  • 또한 어떤 버전의 JDK를 사용하고 있습니까?