2013-04-05 2 views
5

C에서 문자열 배열에 c 내장 bsearch를 사용하려고하면 혼란 스럽습니다. 여기 코드가 있습니다. 문자열 배열 검색을 위해 내장 strcmp를 사용할 수 있다는 것을 알고 있지만 왜 작동하지 않는지 알지 못하기 때문에 디버깅 목적으로 myStrCmp를 포함 시켰습니다.문자열 배열에 bsearch를 사용하는 데 문제가 있습니다.

const char *stateNames[] = {"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "Washington DC", "West Virginia", "Wisconsin", "Wyoming"}; 

int myStrCmp(const void *s1, const void *s2) { 
    printf("myStrCmp: s1(%p): %s, s2(%p): %s\n", s1, (char *)s1, s2, (char *)s2); 
    return strcmp(s1, s2); 
} 

int determineState(char *state) { 
    printf("state: %s\n", state); 
    for(int i = 0; i < 51; i++) 
    printf("stateNames[%i](%p): %s\n", i, &(stateNames[i]), stateNames[i]); 

    char *found = (char *) bsearch(state, stateNames, 51, sizeof(char *), myStrCmp); 

    if(found == NULL) 
    return -1; 

    return 0; 
} 

이 함수가 앨러 배마를 찾기 위해 호출 될 때 출력 결과 중 일부는 다음과 같습니다. 그 순간 당신이 볼 수 있듯이 당신이 문자를 인쇄하려고하면, 그 검색의 과정에서 bsearch 방문 위치가 (단지 bsearch 호출하기 전에 확인 된 바와 같이)하지만, 출력 유효한 문자열을해야

stateNames[0](0x618440): Alabama 
stateNames[1](0x618448): Alaska 
stateNames[2](0x618450): Arizona 
... 
stateNames[24](0x618500): Missouri 
stateNames[25](0x618508): Montana 
stateNames[26](0x618510): Nebraska 
stateNames[27](0x618518): Nevada 
stateNames[28](0x618520): New Hampshire 
stateNames[29](0x618528): New Jersey 
stateNames[30](0x618530): New Mexico 
stateNames[31](0x618538): New York 
stateNames[32](0x618540): North Carolina 
stateNames[33](0x618548): North Dakota 
stateNames[34](0x618550): Ohio 
stateNames[35](0x618558): Oklahoma 
stateNames[36](0x618560): Oregon 
stateNames[37](0x618568): Pennsylvania 
stateNames[38](0x618570): Rhode Island 
stateNames[39](0x618578): South Carolina 
stateNames[40](0x618580): South Dakota 
stateNames[41](0x618588): Tennessee 
stateNames[42](0x618590): Texas 
stateNames[43](0x618598): Utah 
stateNames[44](0x6185a0): Vermont 
stateNames[45](0x6185a8): Virginia 
stateNames[46](0x6185b0): Washington 
stateNames[47](0x6185b8): Washington DC 
stateNames[48](0x6185c0): West Virginia 
stateNames[49](0x6185c8): Wisconsin 
stateNames[50](0x6185d0): Wyoming 
myStrCmp: s1(0x415430): Alabama, s2(0x618508): 
               UA 
myStrCmp: s1(0x415430): Alabama, s2(0x618570): A 
myStrCmp: s1(0x415430): Alabama, s2(0x618540): PUA 
myStrCmp: s1(0x415430): Alabama, s2(0x618528): 1UA 
myStrCmp: s1(0x415430): Alabama, s2(0x618538): GUA 
myStrCmp: s1(0x415430): Alabama, s2(0x618530): <UA 

* 위치가 가비지입니다. 누구든지 내 실수를 볼 수 있습니까? 덧붙여 나는 같은 나쁜 행동을 얻을 수 (그러나 가깝게 분명히을 따르도록하지 않음) I가 최종 파라미터 세트와 bsearch를 호출 할 때 :

(int(*)(const void*, const void*))strcmp 

감사합니다!

답변

7

const char * 배열을 사용하고 있으므로 bsearch()은 이러한 요소에 대한 포인터를 비교 함수에 전달합니다. 즉, 두 번째 인수에 const char * const *을 수신합니다.

int myStrCmp(const void *s1, const void *s2) { 
    const char *key = s1; 
    const char * const *arg = s2; 
    printf("myStrCmp: s1(%p): %s, s2(%p): %s\n", s1, key, s2, *arg); 
    return strcmp(key, *arg); 
} 
+0

흥미 롭다 : 나는 표준에 의해 보증 될 것으로 기대하지 않았다. 그러나 ISO/IEC 9899 : 2011,'§7.22.5.1'bsearch' 함수는 다음과 같이 읽습니다 : ¶3 compar가 가리키는 비교 함수는 키 객체에 대해 을 가리키는 두 개의 인자로 호출되고, 배열 요소에 그 순서대로. _ 그래서, 행동은 결정적입니다. 당신은'mystrCmp()'함수를'qsort()'와 함께 사용할 수 없다. –

+0

@JonathanLeffler : 예, API는 키에 대한 문자열을 전달할 수 있도록 검색 할 구조체 배열을 갖기 위해'qsort() '와 약간 다르게 정의됩니다. – jxh

1

상태 이름 (또는 키)은 포인터에 대한 포인터 여야합니다. 어디서나 const을 추가/제거 할 필요가 없었습니다. myStrCmp은 문자열을 비교하기 위해 역 참조가 필요합니다. 아래 코드는 내가 생각하는 바를 수행합니다. 감사하지 않으면 알려주세요.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 


const char *stateNames[] = {"Alabama", "Alaska", "Arizona", "Arkansas","California", "Colorado", "Connecticut", "Delaware", "Florida","Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "Washington DC", "West Virginia", "Wisconsin", "Wyoming"}; 

int myStrCmp(const void *s1, const void *s2) { 
    printf("myStrCmp: s1(%p): %s, s2(%p): %s\n", s1, *(char **)s1, s2, *(char**)s2); 
    return strcmp(*(char **) s1, *(char **) s2); 
} 

int determineState(char *state) { 
    printf("state: %s\n", state); 

    for(int i = 0; i < 51; i++) 
     printf("stateNames[%i](%p): %s\n", i, &(stateNames[i]), stateNames[i]); 

    char **found = (char **) bsearch(&state, stateNames, 51, sizeof(char *), myStrCmp); 

    if(found == NULL){ 
     return -1; 
    } else { 
     printf("Found it!: %s\n", *found); 

    } 

    return 0; 
} 

int main(int argc, const char * argv[]) { 
    determineState("Alabama"); 

} 
관련 문제