2013-05-14 1 views
0

iOS 응용 프로그램에 퍼지 검색을 추가하려고합니다. Maurice Aubrey가 double_metaphone을 사용하여 기존 C++ 구현을 사용하여 구현했습니다. http://aspell.net/metaphone/. 나는 그의 메인 클래스 인 double_metaphone.mm을 File Type C++ Source로 설정하고 빌드 할 프로젝트를 얻었다.IOS에서 C++ 클래스를 사용한 후에 잘못된 예외가 발생했습니다.

그러나 DoubleMetaphone 메서드를 호출하면 EXC_BAD_ACCESS 오류가 발생합니다. 내 애플 리케이션의 대부분은 ARC를 사용하고 double_metaphone.mm 클래스에있는 많은 메모리 관리 것들을 볼 수있다. 그것은 내가 그 방법으로 나의 대답을 되 찾으려고 노력하는 방법에 대해 가장 의심 스럽다고 말했다. 다음은 double_metaphone.h의 관련 부분입니다 (메서드 선언을 Calling C++ method from Objective C에 따라 extern "C"로 묶습니다). 여기

void 
DoubleMetaphone(const char *str, 
      char **codes); 

는 double_metaphone.mm의 메소드 구현의 relavant 부분입니다

void 
DoubleMetaphone(const char *str, char **codes) 
{ 
int  length; 
metastring *original; 
metastring *primary; 
metastring *secondary; 
int  current; 
int  last; 

current = 0; 
/* we need the real length and last prior to padding */ 
length = strlen(str); 
last = length - 1; 
original = NewMetaString(str); 
/* Pad original so we can index beyond end */ 
MetaphAdd(original, "  "); 

primary = NewMetaString(""); 
secondary = NewMetaString(""); 
primary->free_string_on_destroy = 0; 
secondary->free_string_on_destroy = 0; 

MakeUpper(original); 

/* skip these when at start of word */ 
if (StringAt(original, 0, 2, "GN", "KN", "PN", "WR", "PS", "")) 
current += 1; 

/* Initial 'X' is pronounced 'Z' e.g. 'Xavier' */ 
if (GetAt(original, 0) == 'X') 
    { 
    MetaphAdd(primary, "S"); /* 'Z' maps to 'S' */ 
    MetaphAdd(secondary, "S"); 
    current += 1; 
    } 

/* main loop */ 
while ((primary->length < 4) || (secondary->length < 4)) 
    { 
    if (current >= length) 
     break; 

    switch (GetAt(original, current)) 

..... 

문이 다른 퍼지 코딩을 선택하고에 문자를 추가하는 경우에 가능한 각 문자의 경우 전체 무리 1 차 및 2 차로 구분됩니다.

..... 

if (primary->length > 4) 
SetAt(primary, 4, '\0'); 

if (secondary->length > 4) 
SetAt(secondary, 4, '\0'); 

*codes = primary->str; 
*++codes = secondary->str; 

DestroyMetaString(original); 
DestroyMetaString(primary); 
DestroyMetaString(secondary); 
} 

마지막으로 다음 코드는이 코드를 호출합니다. 나는 double_metaphone.h를 가져온 다음 방법으로 다음을 수행하십시오

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
static NSString *CellIdentifier = @"Filtered Word"; 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
if (cell == nil) { 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
} 
    Word *word = [self.fetchedResultsController objectAtIndexPath:indexPath]; 

    char *codes; 
    NSString *wordForMetaphone = [NSString stringWithString:word.spelling]; 
    DoubleMetaphone([wordForMetaphone UTF8String], &codes); 
    NSLog(@"doubleMetaphone code = %s", codes); 

    cell.textLabel.text = word.spelling; 

return cell; 
} 

로그 메시지없이 문제를 실행하는 것 같다,하지만 cell.textLable.text = word.spellingEXC_BAD_ACCESS 오류를 트리거합니다. 내가 코드를 단계별로 실행할 때 나는 po word를 쓸 수 없다. 둘 중 하나를 적는다 - 나는 C++ 코드가 포인터/메모리를 날려 버리고 있다고 생각하고있다. 그러나 나는 그것을 고치는 것을 어디에서 시작해야할지 정말로 모른다.

참고 : 처음에는 방금 [word.spelling UTF*String]을 전달했지만 동일한 메모리 문제가 발생했습니다. word.spelling == @"a" 처음으로 코드를 살펴보십시오. 4 줄의 코드를 주석 처리하면 앱이 정상적으로 실행됩니다.

나는 char * 코드를 설정하고 올바르게 참조 했으므로이 문제에 기여할 수 있다고 생각하고 있습니다. 기본 및 보조 배열로해서는 안됩니다.

나는 때문에 경고가 C++ deprecated conversion from string constant to 'char*'를 참조하십시오 " '숯불 *'상수 문자열에서 사용되지 않는 변환"의

DoubleMetaphone(char *str, char **codes) 

에서 DoubleMetaphone 방법의 정의를 변경했다. C++ 클래스에는 const char *로 전환해야했던 몇 가지 다른 메소드가 있습니다. 문제의 일부가 아니길 바랄뿐입니다.

도와주세요!

+0

"단어"란 무엇입니까? "세포"는 어디에서 얻었습니까? –

+0

Word는 내 모델의 객체입니다. double_metaphone 구현을 테스트하기 위해 단어 표 (사전 앱)를 가져 와서 셀이 그려지는 동안 각 메타 폰 코드를 기록하도록했습니다. 코드 스 니펫은 tableView : cellForRowAtIndexPath에서 가져온 것입니다. 표와 관련된 fetchedResultsController에서 맞춤법을 사용하여 올바른 단어를 가져옵니다. –

+0

그건 아무 말도하지 않습니다. –

답변

0

귀하의 문제는 너무 ++codes가 유효하지 않은 포인터가 (당신은 아마 다음에 저장되는 일이 중요한 일을 덮어 쓰는 것입니다,

*++codes = secondary->str; 

당신은 함수에 char*에 대한 포인터를 전달하는 것입니다 호출 함수에 codes).

: - "차"에 대한 하나 "차"에 대한 한 - 또는이 같은 배열에 대한 포인터를 전달할 수 두 char** 매개 변수를 전달할 수 있습니다 당신이 두 가지를 반환하려면

,

char* outputs[2] = {0, 0}; 
DoubleMetaphone([wordForMetaphone UTF8String], outputs); 
NSLog(@"doubleMetaphone primary = %s, secondary = %s", outputs[0], outputs[1]); 

... 
// In DoubleMetaphone: 
codes[0] = primary->str; 
codes[1] = secondary->str; 
+0

감사합니다. –

0

또한 내 표준 C++ 11 버전 double_metaphone을 사용할 수도 있습니다. 이 경우 #include을 변경하지 않고 .mm (Objective-C++) 파일로 직접 보내야하며 std::string에서 NSString으로 변환하거나 NSString을 콜백 버전을 사용하여 직접 작성할 수 있습니다.

관련 문제