1

我正在做一个家庭作业,我需要使用 char 数组而不是字符串和 qsort/bsearch。在下面对 bsearch 的调用中,我知道我传递了错误的 Entry 大小,但我不确定如何获得实际大小,因此我的 compareEntries 函数找不到正确的对象。

谁能帮我理解我错过了什么?

#include  <iostream>

using  namespace  std;


typedef Entry*  EntryPtr;
class  Dictionary
{
    public  :
        Dictionary( const char  *filename );
        ~Dictionary();
        const char  *lookupDefinition( const char  *word );

    private  :
        int m_numEntries;
        EntryPtr *m_entries;
        static int compareEntries(const void *leftSide, const void *rightSide);
};

int Dictionary::compareEntries(const void *leftSide, const void *rightSide)
{
    EntryPtr lside = (EntryPtr) leftSide;
    EntryPtr rside = (EntryPtr) rightSide;

    return strcmp(lside->Word, rside->Word);
}

const char *Dictionary::lookupDefinition(const char *word)
{
    if (m_numEntries == 0)
        return 0;

    EntryPtr result = (EntryPtr) bsearch(word, m_entries, 
        m_numEntries, sizeof(m_entries[0]), Dictionary::compareEntries);

    return result->Definition;
}

class Entry
{
        public:
                Entry(const char *line);
                char *Word;
                char *Definition;
};

int  main()
{
    Dictionary  dict( "C:\\path\\file.txt" );
    dict.lookupDefinition("chair");
    return  0;
}
4

5 回答 5

2

为什么不起作用sizeof(Entry)

再次更改-我认为大小应该是指针的大小....

EntryPtr tmp = new Entry("");
tmp->Word = word;

EntryPtr result = (EntryPtr) bsearch(tmp, m_entries, 
        m_numEntries, sizeof(EntryPtr), Dictionary::compareEntries);
于 2010-03-09T22:14:21.003 回答
1

你知道这bsearch需要排序输入,对吧?

sizeof(m_entries[0])对我来说看起来非常好。

编辑:现在我看到了问题。您的 Dictionary 类包含一个指针数组。问题出在 compareEntries 函数中,您将传递的指针转换为EntryPtr; 您需要将它们转换为EntryPtr *

编辑 2:正如Amit Kumar所指出的,您需要更改发送给 bsearch 的关键参数,或者您需要意识到您在 compareEntries 中收到的指针不指向相同的类型,并且需要两种不同的类型转换。

于 2010-03-09T22:19:06.263 回答
1

问题是使用的比较器函数bsearch期望word是 type Entry*(或m_entriestype char**)。

于 2010-03-09T22:22:46.880 回答
0

仔细阅读手册。

其他人提出的观点的总结,以及其他几个问题:

  • 您对sizeof的使用是正确的。

  • 您应该传递一个指向包含您要查找的键的条目的指针。实际上键可以是任何东西,它会作为第一个参数传递给比较函数,你只需要将两个参数都转换为正确的类型。(比较函数仍应与项目排序的顺序相对应。)

  • 比较函数中的强制转换不正确。比较函数接收指向元素的指针(在您的情况下是指向条目的指针,因此比较函数接收指向条目指针的指针)。

  • 您将结果转换为错误的类型。该函数再次返回指向数组中元素的指针(指向 Entry 的指针)。

  • 如果密钥不存在,您不会检查结果是否为 NULL。

  • 您可能会放弃一级间接(您真的需要一个指针数组而不是一个条目数组吗?)

  • 你应该把它作为一个很好的例子来说明人们在谈论类型安全的优点时的意思:在你的代码中,几乎所有类型都混在一起了,你用错误的类型做了错误的事情,但没有一个来自于编译器。如果你搞砸了,这就是你得到的void*,除非你确切地知道你在做什么。

为了它的乐趣,拥有一个指针数组需要大量的间接来获得结果:

#include <cstdlib>
#include <string>
#include <iostream>

int compare_string(const void* a, const void* b)
{
    return ((const std::string*)a)->compare(**(const std::string**)b);
}

int main()
{
    std::string a("a"), b("b"), c("c");
    std::string* array[3] = { &a, &b, &c };
    std::string key = "b";
    std::string** result = (std::string**)bsearch(&key, array, 3, sizeof(std::string*), compare_string);
    if (result) std::cout << **result << '\n';
}

IMO,实现您自己的类型安全 bsearch 所需的时间比弄清楚所有这些并对其进行测试和调试所需的时间更少。

于 2010-03-09T22:47:54.943 回答
0

sizeof(Entry) 会起作用。大多数情况下 sizeof 应该用于类型而不是实例。

大小(条目)

最好是

条目 e;
大小(e);

或者

条目* e;
大小(* e);

都给出相同的结果。

#include "stdio.h"
class Entry {
  double e;
  int i;
};
int main() {
  Entry e;
  printf("%d\n", sizeof(e));
  printf("%d\n", sizeof(Entry));
  printf("%d\n", sizeof(*(&e)));
  return 0;
}
于 2010-03-09T23:11:59.533 回答