比较函数中的Bsearch和垃圾值

时间:2017-02-11 02:52:34

标签: c 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

我无法理解这种行为。

1 个答案:

答案 0 :(得分:1)

如果您正在搜索int数组,则会将const void *参数转换为比较函数int *,不是吗?

您正在搜索char *数组,因此您需要将const void *参数转换为char ** - 并且您需要为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; } 个参数值得找到。

您的代码所需的更改很少但至关重要:

char **

比较器函数现在需要两个char *值,并捕获每个值指向的字符串。

调用的第一个参数需要是const char *search = "company";变量的地址;因此增加了变量const char *file = "/usr/share/dict/words";

次要清理包括使比较器函数保持静态(主要是为了满足我的迂腐默认编译选项 - 尽管最好在函数被定义之前声明它们),并使用变量fopen()来避免(接近)重复在调用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! 和错误消息之间。

示例输出(在带有macOS Sierra 10.12.3的Mac上运行):

public function paginacija_pjesme($limit = 10, $offset = 0) {

    $query = $this->db->select('p.pjesma_id, p.naslov, i.naziv')
        ->from('pjesma p')
        ->join('izvodi_pjesmu ip', 'p.pjesma_id = ip.pjesma_pjesma_id', 'left')
        ->join('izvodjac i', 'i.izvodjac_id = ip.izvodjac_izvodjac_id', 'left')
        ->limit($limit, $offset)
        ->get();

    return $query->result();
}