2017-02-11 6 views
-1

に、私は次のプログラムがありますBSEARCHとジャンク値比較関数

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

#define DICT_BUFSIZE 64 

int compar(const void * a, const void * b) 
{ 
    const char* c1 = (const char*)a; 
    const char* c2 = (const char*)b; 

    printf("c1: %s | c2: %s\n", c1, c2); 

    return strcmp(c1, c2); 
} 

int main (void) 
{ 
    FILE*  fdict; 
    uint32_t i; 
    char** dict = NULL; 
    size_t size = 0; 
    size_t size_alloced = 0; 
    char  buf[DICT_BUFSIZE]; 

    fdict = fopen("/usr/share/dict/words", "r"); 
    if (!fdict) { 
     printf("Could not open \"%s\": %s\n", "usr/share/dict/words", strerror(errno)); 
     exit(1); 
    } 

    for (i = 0; fgets(buf, DICT_BUFSIZE, fdict); ++i) { 
     size_t len; 

     if (i == size_alloced) { 
      dict = realloc(dict, (i +50000) * sizeof(*dict)); 
      size_alloced += 50000; 
     } 
     len = strlen(buf); 
     dict[i] = malloc(len); 

     memcpy(dict[i], buf, len -1); 
     dict[i][len -1] = '\0'; 
    } 
    size = i; 

    //for (i = 0; i < size; i++) 
     //printf("%s\n", dict[i]); 

    if(bsearch("company", dict, size, sizeof(*dict), compar)) 
     printf("Found!\n"); 

    for (i = 0; i < size; ++i) 
     free(dict[i]); 
    free(dict); 

    fclose(fdict); 

    return 0; 
} 

「C1」の変数(検索されるキー)が正しく表示されている「比較例」機能では、しかし、ジャンク出力がありますv2変数に格納されます。

は、ここでの出力例です:

c1: company | c2: ��� 
c1: company | c2: �$z 
c1: company | c2: ��I 
c1: company | c2: ��7 
c1: company | c2: P�. 
c1: company | c2: �b3 
c1: company | c2: �1 
c1: company | c2: P�/ 
c1: company | c2: ��0 
c1: company | c2: PC0 
c1: company | c2: @g0 
c1: company | c2: y0 
c1: company | c2: 0�0 
c1: company | c2: ��0 
c1: company | c2: `�0 
c1: company | c2: ��0 
c1: company | c2: 
c1: company | c2: P�0 

私は、この動作を理解することはできません。

+0

私ははsizeof(* dictのは)あなたはそれがないと思う値を持っているとは思いません。 – Irisshpunk

+0

私はすぐにそれを犯人と考えましたが、何が間違っているのか見当たりません。 – Nick

答えて

1

intの配列を検索している場合は、const void *引数を比較関数int *に変換していますか?

あなたはchar *の配列を検索しているので、あなたはchar **const void *引数を変換する必要があります - あなたが発見される値のchar **引数を渡す必要があります。あなたのコードに必要な

変更は最小限に抑えますが不可欠である:

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

#define DICT_BUFSIZE 64 

static int compar(const void *a, const void *b) 
{ 
    const char *c1 = *(const char **)a; 
    const char *c2 = *(const char **)b; 

    printf("c1: %s | c2: %s\n", c1, c2); 

    return strcmp(c1, c2); 
} 

int main (void) 
{ 
    FILE*  fdict; 
    uint32_t i; 
    char** dict = NULL; 
    size_t size = 0; 
    size_t size_alloced = 0; 
    char  buf[DICT_BUFSIZE]; 
    const char *file = "/usr/share/dict/words"; 

    fdict = fopen(file, "r"); 
    if (!fdict) { 
     printf("Could not open \"%s\": %s\n", file, strerror(errno)); 
     exit(1); 
    } 

    for (i = 0; fgets(buf, DICT_BUFSIZE, fdict); ++i) { 
     size_t len; 

     if (i == size_alloced) { 
      dict = realloc(dict, (i +50000) * sizeof(*dict)); 
      size_alloced += 50000; 
     } 
     len = strlen(buf); 
     dict[i] = malloc(len); 

     memcpy(dict[i], buf, len -1); 
     dict[i][len -1] = '\0'; 
    } 
    size = i; 

    //for (i = 0; i < size; i++) 
     //printf("%s\n", dict[i]); 

    const char *search = "company"; 
    if(bsearch(&search, dict, size, sizeof(*dict), compar)) 
     printf("Found!\n"); 

    for (i = 0; i < size; ++i) 
     free(dict[i]); 
    free(dict); 

    fclose(fdict); 

    return 0; 
} 

コンパレータ機能は現在、2つのchar **値を期待して、これらのポイントのそれぞれに文字列をキャプチャします。

呼び出しの最初の引数は、char *変数のアドレスである必要があります。したがって、変数const char *search = "company";の追加。

小規模なクリーンアップには、コンパイル機能を静的にすることが含まれています(主に私のペダルのデフォルトのコンパイルオプションを満たすために - 関数が定義される前に宣言されていることが最善ですが)、変数const char *file = "/usr/share/dict/words";fopen()とエラーメッセージ。

サンプル出力(MacOSのシエラ10.12.3を搭載したMac上で実行):

c1: company | c2: modifier 
c1: company | c2: eagle 
c1: company | c2: Canarian 
c1: company | c2: counteridea 
c1: company | c2: citropten 
c1: company | c2: compulsoriness 
c1: company | c2: coelenteric 
c1: company | c2: Colossian 
c1: company | c2: commonable 
c1: company | c2: compilation 
c1: company | c2: compagination 
c1: company | c2: compatriot 
c1: company | c2: comparition 
c1: company | c2: comparable 
c1: company | c2: companionate 
c1: company | c2: companionway 
c1: company | c2: comparability 
c1: company | c2: company 
Found! 
+0

ありがとう、面白かったです!訂正:bsearchの "キー"は、ポインタへのポインタとして渡されません。それとは別に、次のWebサイトの2番目の例が私のプログラムの問題なしでどのように動作するのかもわかりませんでした。http://www.cplusplus.com/reference/cstdlib/bsearch/ – Nick

+0

'qsort()'と同じ比較関数を使用すると、データをソートすることができます。両方の引数を同じ型にする必要があります。 'bsearch()'のキーは常に最初の引数として渡されるので、 'static int compar(const void * a、const void * b) {const char * c1 =(const char *)a; const char * c2 = *(const char **)b; '非対称キャスティングを使用していますが、並べ替えと検索のために1つの関数を作成する必要があります。だから、もしあなたが 'bsearch()'でコンパレータを使うつもりなら、あなたが提案したようにすることができます。私はそれをしないだろう。 –

+0

http://www.cplusplus.com/reference/cstdlib/bsearch/リンクの2番目の例は、 'char strvalues [] [20] = {" some "、" example "、" strings "、" here " char * strvalues [] = {"some"、 "example"、 "strings"、 "here"}; ' - そして違いは本当に重要です。後者はあなたが持っているものと同等です。 –

関連する問題