2013-04-05 7 views
5

Cの組み込みのbsearchをCの文字列に使用しようとすると、混乱します。ここにコードがあります。私はあなたが文字列の配列を検索するための組み込み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; 
} 

この関数がアラバマを探すために呼び出されたときの出力の一部を示します。その時

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 

あなたが見ることができるようにあなたが文字を印刷しようとすると、その検索の過程でのbsearchが訪れた場所は、有効な文字列(ただのbsearchを呼び出す前に確認したもの)が、出力を持っている必要があります*場所はゴミです。誰か私の間違いを見ることができますか?ちなみに私は、同じ悪い振る舞いを得る(しかしとして密接に明らかにそれに従うことを得ることはありません)私は、最終的なパラメータセットでのbsearchを呼び出すとき:

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

ありがとう!

答えて

7

const char *の配列を使用しているため、bsearch()はこれらの要素へのポインタを比較関数に渡します。つまり、2番目の引数には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'が指す比較関数は、キーオブジェクトに対して を指す2つの引数で呼び出され、配列要素にその順番で並べ替えます。したがって、振る舞いは確定的です。しかし、 '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"); 

} 
関連する問題