5

C の文字列の配列に対して c の組み込み bsearch を使用しようとすると、混乱する動作が発生します。コードは次のとおりです。組み込みの strcmp を使用して文字列の配列を検索できることは知っていますが、なぜ機能しないのかわからなかったので、デバッグ目的で myStrCmp を含めました。

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;
}

Alabama を検索するためにこの関数が呼び出されたときの出力の一部を次に示します。

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 を呼び出す前に確認したように)、その場所で char * を出力しようとすると、出力はガベージになります。誰かが私の間違いを見ることができますか? ちなみに、最後のパラメーターを次のように設定して bsearch を呼び出すと、同じ悪い動作が発生します (ただし、明らかにそれを厳密に追跡することはできません)。

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

ありがとう!

4

2 に答える 2

8

の配列を使用しているためconst char *bsearch()これらの要素へのポインタが比較関数に渡されます。const char * const *つまり、 2 番目の引数で受け取ります。

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);
}
于 2013-04-05T02:37:02.240 に答える
1

状態名 (またはキー) は、ポインターへのポインターである必要があります。constどこ にも追加/削除する必要はありませんでした。myStrCmp文字列を比較するには、1 つ逆参照する必要があります。以下のコードは、私が思うことを行います。そうでない場合はお知らせください、ありがとう。

#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");

}
于 2017-11-21T18:44:43.360 に答える